- Update user32_winetest to Wine-1.1.31.
[reactos.git] / rostests / winetests / user32 / text.c
1 /*
2 * DrawText tests
3 *
4 * Copyright (c) 2004 Zach Gorman
5 * Copyright 2007 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
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)
32
33 static void test_DrawTextCalcRect(void)
34 {
35 HWND hwnd;
36 HDC hdc;
37 HFONT hFont, hOldFont;
38 LOGFONTA lf;
39 static CHAR text[] = "Example text for testing DrawText in "
40 "MM_HIENGLISH mode";
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 INT textlen, textheight, heightcheck;
46 RECT rect = { 0, 0, 100, 0 };
47 BOOL ret;
48 DRAWTEXTPARAMS dtp;
49 BOOL conform_xp = TRUE;
50
51 /* Initialization */
52 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
53 0, 0, 200, 200, 0, 0, 0, NULL);
54 ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
55 hdc = GetDC(hwnd);
56 ok(hdc != 0, "GetDC error %u\n", GetLastError());
57 trace("hdc %p\n", hdc);
58 textlen = lstrlenA(text);
59
60 /* LOGFONT initialization */
61 memset(&lf, 0, sizeof(lf));
62 lf.lfCharSet = ANSI_CHARSET;
63 lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
64 lf.lfWeight = FW_DONTCARE;
65 lf.lfHeight = 0; /* mapping mode dependent */
66 lf.lfQuality = DEFAULT_QUALITY;
67 lstrcpyA(lf.lfFaceName, "Arial");
68
69 /* DrawText in MM_HIENGLISH with DT_CALCRECT */
70 SetMapMode(hdc, MM_HIENGLISH);
71 lf.lfHeight = 100 * 9 / 72; /* 9 point */
72 hFont = CreateFontIndirectA(&lf);
73 ok(hFont != 0, "CreateFontIndirectA error %u\n",
74 GetLastError());
75 hOldFont = SelectObject(hdc, hFont);
76
77 textheight = DrawTextA(hdc, text, textlen, &rect, DT_CALCRECT |
78 DT_EXTERNALLEADING | DT_WORDBREAK | DT_NOCLIP | DT_LEFT |
79 DT_NOPREFIX);
80 ok( textheight, "DrawTextA error %u\n", GetLastError());
81
82 trace("MM_HIENGLISH rect.bottom %d\n", rect.bottom);
83 ok(rect.bottom < 0, "In MM_HIENGLISH, DrawText with "
84 "DT_CALCRECT should return a negative rectangle bottom. "
85 "(bot=%d)\n", rect.bottom);
86
87 SelectObject(hdc, hOldFont);
88 ret = DeleteObject(hFont);
89 ok( ret, "DeleteObject error %u\n", GetLastError());
90
91
92 /* DrawText in MM_TEXT with DT_CALCRECT */
93 SetMapMode(hdc, MM_TEXT);
94 lf.lfHeight = -MulDiv(9, GetDeviceCaps(hdc,
95 LOGPIXELSY), 72); /* 9 point */
96 hFont = CreateFontIndirectA(&lf);
97 ok(hFont != 0, "CreateFontIndirectA error %u\n",
98 GetLastError());
99 hOldFont = SelectObject(hdc, hFont);
100
101 textheight = DrawTextA(hdc, text, textlen, &rect, DT_CALCRECT |
102 DT_EXTERNALLEADING | DT_WORDBREAK | DT_NOCLIP | DT_LEFT |
103 DT_NOPREFIX);
104 ok( textheight, "DrawTextA error %u\n", GetLastError());
105
106 trace("MM_TEXT rect.bottom %d\n", rect.bottom);
107 ok(rect.bottom > 0, "In MM_TEXT, DrawText with DT_CALCRECT "
108 "should return a positive rectangle bottom. (bot=%d)\n",
109 rect.bottom);
110
111 /* empty or null text should in some cases calc an empty rectangle */
112
113 SetRect( &rect, 10,10, 100, 100);
114 heightcheck = textheight = DrawTextExA(hdc, text, 0, &rect, DT_CALCRECT, NULL );
115 ok( !EMPTY(rect) && !MODIFIED(rect),
116 "rectangle should NOT be empty got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
117 if (textheight != 0) /* Windows 98 */
118 {
119 win_skip("XP conformity failed, skipping XP tests. Probably win9x\n");
120 conform_xp = FALSE;
121 }
122 else
123 ok(textheight==0,"Got textheight from DrawTextExA\n");
124
125 SetRect( &rect, 10,10, 100, 100);
126 textheight = DrawTextA(hdc, text, 0, &rect, DT_CALCRECT);
127 ok( !EMPTY(rect) && !MODIFIED(rect),
128 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
129 rect.left, rect.top, rect.right, rect.bottom );
130 if (conform_xp)
131 ok(textheight==0,"Got textheight from DrawTextA\n");
132 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
133
134 SetRect( &rect, 10,10, 100, 100);
135 SetLastError( 0);
136 heightcheck = textheight = DrawTextExA(hdc, emptystring, -1, &rect, DT_CALCRECT, NULL );
137 ok( EMPTY(rect),
138 "rectangle should be empty got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
139 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
140
141 SetRect( &rect, 10,10, 100, 100);
142 textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT);
143 ok( EMPTY(rect),
144 "rectangle should be empty got %d,%d-%d,%d\n",
145 rect.left, rect.top, rect.right, rect.bottom );
146 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
147 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
148
149 SetRect( &rect, 10,10, 100, 100);
150 SetLastError( 0);
151 heightcheck = textheight = DrawTextExA(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
152 ok( EMPTY(rect) || !MODIFIED(rect),
153 "rectangle should be empty or not modified got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
154 if (!textheight) /* Windows NT 4 */
155 {
156 if (conform_xp)
157 win_skip("XP conformity failed, skipping XP tests. Probably winNT\n");
158 conform_xp = FALSE;
159 }
160 else
161 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
162
163 SetRect( &rect, 10,10, 100, 100);
164 textheight = DrawTextA(hdc, NULL, -1, &rect, DT_CALCRECT);
165 ok( EMPTY(rect) || !MODIFIED(rect),
166 "rectangle should be empty or NOT modified got %d,%d-%d,%d\n",
167 rect.left, rect.top, rect.right, rect.bottom );
168 if (conform_xp)
169 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
170 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
171
172 SetRect( &rect, 10,10, 100, 100);
173 heightcheck = textheight = DrawTextExA(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
174 ok( !EMPTY(rect) && !MODIFIED(rect),
175 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
176 if (conform_xp)
177 ok(textheight==0,"Got textheight from DrawTextExA\n");
178
179 SetRect( &rect, 10,10, 100, 100);
180 textheight = DrawTextA(hdc, NULL, 0, &rect, DT_CALCRECT);
181 ok( !EMPTY(rect) && !MODIFIED(rect),
182 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
183 rect.left, rect.top, rect.right, rect.bottom );
184 if (conform_xp)
185 ok(textheight==0,"Got textheight from DrawTextA\n");
186 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
187
188 /* DT_SINGLELINE tests */
189
190 SetRect( &rect, 10,10, 100, 100);
191 heightcheck = textheight = DrawTextExA(hdc, text, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
192 ok( !EMPTY(rect) && !MODIFIED(rect),
193 "rectangle should NOT be empty got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
194 if (conform_xp)
195 ok(textheight==0,"Got textheight from DrawTextExA\n");
196
197 SetRect( &rect, 10,10, 100, 100);
198 textheight = DrawTextA(hdc, text, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
199 ok( !EMPTY(rect) && !MODIFIED(rect),
200 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
201 rect.left, rect.top, rect.right, rect.bottom );
202 if (conform_xp)
203 ok(textheight==0,"Got textheight from DrawTextA\n");
204 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
205
206 SetRect( &rect, 10,10, 100, 100);
207 SetLastError( 0);
208 heightcheck = textheight = DrawTextExA(hdc, emptystring, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
209 ok( !EMPTY(rect) && MODIFIED(rect),
210 "rectangle should be modified got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
211 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
212
213 SetRect( &rect, 10,10, 100, 100);
214 textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
215 ok( !EMPTY(rect) && MODIFIED (rect),
216 "rectangle should be modified got %d,%d-%d,%d\n",
217 rect.left, rect.top, rect.right, rect.bottom );
218 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
219 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
220
221 SetRect( &rect, 10,10, 100, 100);
222 SetLastError( 0);
223 heightcheck = textheight = DrawTextExA(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
224 ok( (!EMPTY(rect) && MODIFIED(rect)) || !MODIFIED(rect),
225 "rectangle should be modified got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
226 if (conform_xp)
227 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
228
229 SetRect( &rect, 10,10, 100, 100);
230 textheight = DrawTextA(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
231 ok( (!EMPTY(rect) && MODIFIED(rect)) || !MODIFIED(rect),
232 "rectangle should be modified got %d,%d-%d,%d\n",
233 rect.left, rect.top, rect.right, rect.bottom );
234 if (conform_xp)
235 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
236 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
237
238 SetRect( &rect, 10,10, 100, 100);
239 heightcheck = textheight = DrawTextExA(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
240 ok( !EMPTY(rect) && !MODIFIED(rect),
241 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n", rect.left, rect.top, rect.right, rect.bottom );
242 if (conform_xp)
243 ok(textheight==0,"Got textheight from DrawTextExA\n");
244
245 SetRect( &rect, 10,10, 100, 100);
246 textheight = DrawTextA(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
247 ok( !EMPTY(rect) && !MODIFIED(rect),
248 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
249 rect.left, rect.top, rect.right, rect.bottom );
250 if (conform_xp)
251 ok(textheight==0,"Got textheight from DrawTextA\n");
252 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
253
254 /* further tests with 0 count, NULL and empty strings */
255 heightcheck = textheight = DrawTextA(hdc, text, 0, &rect, 0);
256 if (conform_xp)
257 ok(textheight==0,"Got textheight from DrawTextA\n");
258 textheight = DrawTextExA(hdc, text, 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, 0, &rect, 0);
263 if (conform_xp)
264 ok(textheight==0,"Got textheight from DrawTextA\n");
265 textheight = DrawTextExA(hdc, emptystring, 0, &rect, 0, NULL );
266 if (conform_xp)
267 ok(textheight==0,"Got textheight from DrawTextExA\n");
268 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
269 heightcheck = textheight = DrawTextA(hdc, NULL, 0, &rect, 0);
270 if (conform_xp)
271 ok(textheight==0,"Got textheight from DrawTextA\n");
272 textheight = DrawTextExA(hdc, NULL, 0, &rect, 0, NULL );
273 if (conform_xp)
274 ok(textheight==0,"Got textheight from DrawTextExA\n");
275 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
276 heightcheck = textheight = DrawTextA(hdc, emptystring, -1, &rect, 0);
277 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
278 textheight = DrawTextExA(hdc, emptystring, -1, &rect, 0, NULL );
279 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
280 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
281 heightcheck = textheight = DrawTextA(hdc, NULL, -1, &rect, 0);
282 if (conform_xp)
283 ok(textheight!=0,"Failed to get textheight from DrawTextA\n");
284 textheight = DrawTextExA(hdc, NULL, -1, &rect, 0, NULL );
285 if (conform_xp)
286 ok(textheight!=0,"Failed to get textheight from DrawTextExA\n");
287 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
288 heightcheck = textheight = DrawTextA(hdc, NULL, 10, &rect, 0);
289 ok(textheight==0,"Got textheight from DrawTextA\n");
290 textheight = DrawTextExA(hdc, NULL, 10, &rect, 0, NULL );
291 ok(textheight==0,"Got textheight from DrawTextA\n");
292 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
293
294
295 /* invalid dtp size test */
296 dtp.cbSize = -1; /* Invalid */
297 dtp.uiLengthDrawn = 1337;
298 textheight = DrawTextExA(hdc, text, 0, &rect, 0, &dtp);
299 ok(textheight==0,"Got textheight from DrawTextExA\n");
300 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
301 dtp.uiLengthDrawn = 1337;
302 textheight = DrawTextExA(hdc, emptystring, 0, &rect, 0, &dtp);
303 ok(textheight==0,"Got textheight from DrawTextExA\n");
304 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
305 dtp.uiLengthDrawn = 1337;
306 textheight = DrawTextExA(hdc, NULL, 0, &rect, 0, &dtp);
307 ok(textheight==0,"Got textheight from DrawTextExA\n");
308 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
309 dtp.uiLengthDrawn = 1337;
310 textheight = DrawTextExA(hdc, emptystring, -1, &rect, 0, &dtp);
311 ok(textheight==0,"Got textheight from DrawTextExA\n");
312 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
313 dtp.uiLengthDrawn = 1337;
314 textheight = DrawTextExA(hdc, NULL, -1, &rect, 0, &dtp);
315 ok(textheight==0,"Got textheight from DrawTextExA\n");
316 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
317
318 /* Margin calculations */
319 dtp.cbSize = sizeof(dtp);
320 dtp.iLeftMargin = 0;
321 dtp.iRightMargin = 0;
322 SetRect( &rect, 0, 0, 0, 0);
323 DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
324 textlen = rect.right; /* Width without margin */
325 dtp.iLeftMargin = 8;
326 SetRect( &rect, 0, 0, 0, 0);
327 DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
328 ok(rect.right==dtp.iLeftMargin+textlen ,"Incorrect left margin calculated rc(%d,%d)\n", rect.left, rect.right);
329 dtp.iLeftMargin = 0;
330 dtp.iRightMargin = 8;
331 SetRect( &rect, 0, 0, 0, 0);
332 DrawTextExA(hdc, text, -1, &rect, DT_CALCRECT, &dtp);
333 ok(rect.right==dtp.iRightMargin+textlen ,"Incorrect right margin calculated rc(%d,%d)\n", rect.left, rect.right);
334
335 /* Wide char versions */
336 SetRect( &rect, 10,10, 100, 100);
337 SetLastError( 0);
338 heightcheck = textheight = DrawTextExW(hdc, textW, 0, &rect, DT_CALCRECT, NULL );
339 if( GetLastError() != ERROR_CALL_NOT_IMPLEMENTED) {
340 ok( !EMPTY(rect) && !MODIFIED(rect),
341 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
342 rect.left, rect.top, rect.right, rect.bottom );
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( !EMPTY(rect) && !MODIFIED(rect),
348 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
349 rect.left, rect.top, rect.right, rect.bottom );
350 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
351 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
352
353 SetRect( &rect, 10,10, 100, 100);
354 heightcheck = textheight = DrawTextExW(hdc, emptystringW, -1, &rect, DT_CALCRECT, NULL );
355 ok( EMPTY(rect),
356 "rectangle should be empty got %d,%d-%d,%d\n",
357 rect.left, rect.top, rect.right, rect.bottom );
358 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
359
360 SetRect( &rect, 10,10, 100, 100);
361 textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT);
362 ok( EMPTY(rect),
363 "rectangle should be empty got %d,%d-%d,%d\n",
364 rect.left, rect.top, rect.right, rect.bottom );
365 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
366 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
367
368 SetRect( &rect, 10,10, 100, 100);
369 heightcheck = textheight = DrawTextExW(hdc, NULL, 0, &rect, DT_CALCRECT, NULL );
370 ok( !EMPTY(rect) && !MODIFIED(rect),
371 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
372 rect.left, rect.top, rect.right, rect.bottom );
373 if (textheight) /* windows 2000 */
374 {
375 if (conform_xp)
376 win_skip("XP conformity failed, skipping XP tests. Probably win 2000\n");
377 conform_xp = FALSE;
378 }
379 else
380 ok(textheight==0,"Got textheight from DrawTextExW\n");
381
382 SetRect( &rect, 10,10, 100, 100);
383 textheight = DrawTextW(hdc, NULL, 0, &rect, DT_CALCRECT);
384 ok( !EMPTY(rect) && !MODIFIED(rect),
385 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
386 rect.left, rect.top, rect.right, rect.bottom );
387 if (conform_xp)
388 ok(textheight==0,"Got textheight from DrawTextW\n");
389 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
390
391 if (conform_xp) {
392 /* Crashes on NT4 */
393 SetRect( &rect, 10,10, 100, 100);
394 heightcheck = textheight = DrawTextExW(hdc, NULL, -1, &rect, DT_CALCRECT, NULL );
395 ok( !EMPTY(rect) && !MODIFIED(rect),
396 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
397 rect.left, rect.top, rect.right, rect.bottom );
398 ok(textheight==0,"Got textheight from DrawTextExW\n");
399
400 SetRect( &rect, 10,10, 100, 100);
401 textheight = DrawTextW(hdc, NULL, -1, &rect, DT_CALCRECT);
402 ok( !EMPTY(rect) && !MODIFIED(rect),
403 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
404 rect.left, rect.top, rect.right, rect.bottom );
405 ok(textheight==0,"Got textheight from DrawTextW\n");
406 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
407 }
408
409
410 /* DT_SINGLELINE tests */
411
412 heightcheck = textheight = DrawTextExW(hdc, textW, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
413 ok( !EMPTY(rect) && !MODIFIED(rect),
414 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
415 rect.left, rect.top, rect.right, rect.bottom );
416 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
417
418 SetRect( &rect, 10,10, 100, 100);
419 textheight = DrawTextW(hdc, textW, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
420 ok( !EMPTY(rect) && !MODIFIED(rect),
421 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
422 rect.left, rect.top, rect.right, rect.bottom );
423 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
424 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
425
426 SetRect( &rect, 10,10, 100, 100);
427 heightcheck = textheight = DrawTextExW(hdc, emptystringW, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
428 ok( !EMPTY(rect) && MODIFIED(rect),
429 "rectangle should be modified got %d,%d-%d,%d\n",
430 rect.left, rect.top, rect.right, rect.bottom );
431 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
432
433 SetRect( &rect, 10,10, 100, 100);
434 textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
435 ok( !EMPTY(rect) && MODIFIED(rect),
436 "rectangle should be modified got %d,%d-%d,%d\n",
437 rect.left, rect.top, rect.right, rect.bottom );
438 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
439 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
440
441 if (conform_xp) {
442 /* Crashes on NT4 */
443 SetRect( &rect, 10,10, 100, 100);
444 heightcheck = textheight = DrawTextExW(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
445 ok( !EMPTY(rect) && !MODIFIED(rect),
446 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
447 rect.left, rect.top, rect.right, rect.bottom );
448 ok(textheight==0,"Got textheight from DrawTextExW\n");
449
450 SetRect( &rect, 10,10, 100, 100);
451 textheight = DrawTextW(hdc, NULL, -1, &rect, DT_CALCRECT|DT_SINGLELINE);
452 ok( !EMPTY(rect) && !MODIFIED(rect),
453 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
454 rect.left, rect.top, rect.right, rect.bottom );
455 ok(textheight==0,"Got textheight from DrawTextW\n");
456 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
457 }
458
459 SetRect( &rect, 10,10, 100, 100);
460 heightcheck = textheight = DrawTextExW(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE, NULL );
461 ok( !EMPTY(rect) && !MODIFIED(rect),
462 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
463 rect.left, rect.top, rect.right, rect.bottom );
464 if (conform_xp)
465 ok(textheight==0,"Got textheight from DrawTextExW\n");
466
467 SetRect( &rect, 10,10, 100, 100);
468 textheight = DrawTextW(hdc, NULL, 0, &rect, DT_CALCRECT|DT_SINGLELINE);
469 ok( !EMPTY(rect) && !MODIFIED(rect),
470 "rectangle should NOT be empty and NOT modified got %d,%d-%d,%d\n",
471 rect.left, rect.top, rect.right, rect.bottom );
472 if (conform_xp)
473 ok(textheight==0,"Got textheight from DrawTextW\n");
474 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
475
476 /* further tests with NULL and empty strings */
477 heightcheck = textheight = DrawTextW(hdc, textW, 0, &rect, 0);
478 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
479 textheight = DrawTextExW(hdc, textW, 0, &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 heightcheck = textheight = DrawTextW(hdc, emptystringW, 0, &rect, 0);
483 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
484 textheight = DrawTextExW(hdc, emptystringW, 0, &rect, 0, NULL );
485 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
486 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
487 heightcheck = textheight = DrawTextW(hdc, NULL, 0, &rect, 0);
488 if (conform_xp)
489 ok(textheight==0,"Got textheight from DrawTextW\n");
490 textheight = DrawTextExW(hdc, NULL, 0, &rect, 0, NULL );
491 if (conform_xp)
492 ok(textheight==0,"Got textheight from DrawTextExW\n");
493 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
494 heightcheck = textheight = DrawTextW(hdc, emptystringW, -1, &rect, 0);
495 ok(textheight!=0,"Failed to get textheight from DrawTextW\n");
496 textheight = DrawTextExW(hdc, emptystringW, -1, &rect, 0, NULL );
497 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
498 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
499 if (conform_xp) {
500 /* Crashes on NT4 */
501 heightcheck = textheight = DrawTextW(hdc, NULL, -1, &rect, 0);
502 ok(textheight==0,"Got textheight from DrawTextW\n");
503 textheight = DrawTextExW(hdc, NULL, -1, &rect, 0, NULL );
504 ok(textheight==0,"Got textheight from DrawTextExW\n");
505 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
506 heightcheck = textheight = DrawTextW(hdc, NULL, 10, &rect, 0);
507 ok(textheight==0,"Got textheight from DrawTextW\n");
508 textheight = DrawTextExW(hdc, NULL, 10, &rect, 0, NULL );
509 ok(textheight==0,"Got textheight from DrawTextW\n");
510 ok(textheight == heightcheck,"DrawTextEx and DrawText differ in return\n");
511 }
512
513 dtp.cbSize = -1; /* Invalid */
514 dtp.uiLengthDrawn = 1337;
515 textheight = DrawTextExW(hdc, textW, 0, &rect, 0, &dtp);
516 ok(textheight!=0,"Failed to get textheight from DrawTextExW\n");
517 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
518 dtp.uiLengthDrawn = 1337;
519 textheight = DrawTextExW(hdc, emptystringW, 0, &rect, 0, &dtp);
520 if (conform_xp)
521 ok(textheight==0,"Got textheight from DrawTextExW\n");
522 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
523 dtp.uiLengthDrawn = 1337;
524 textheight = DrawTextExW(hdc, NULL, 0, &rect, 0, &dtp);
525 if (conform_xp)
526 ok(textheight==0,"Got textheight from DrawTextExW\n");
527 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
528 dtp.uiLengthDrawn = 1337;
529 textheight = DrawTextExW(hdc, emptystringW, -1, &rect, 0, &dtp);
530 ok(textheight==0,"Got textheight from DrawTextExW\n");
531 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
532 if (conform_xp) {
533 /* Crashes on NT4 */
534 dtp.uiLengthDrawn = 1337;
535 textheight = DrawTextExW(hdc, NULL, -1, &rect, 0, &dtp);
536 ok(textheight==0,"Got textheight from DrawTextExW\n");
537 ok(dtp.uiLengthDrawn==1337, "invalid dtp.uiLengthDrawn = %i\n",dtp.uiLengthDrawn);
538 }
539 }
540
541 /* More test cases from bug 12226 */
542 SetRect(&rect, 0, 0, 0, 0);
543 textheight = DrawTextA(hdc, emptystring, -1, &rect, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
544 ok(textheight, "DrawTextA error %u\n", GetLastError());
545 ok(0 == rect.left, "expected 0, got %d\n", rect.left);
546 ok(0 == rect.right, "expected 0, got %d\n", rect.right);
547 ok(0 == rect.top, "expected 0, got %d\n", rect.top);
548 ok(rect.bottom, "rect.bottom should not be 0\n");
549
550 SetRect(&rect, 0, 0, 0, 0);
551 textheight = DrawTextW(hdc, emptystringW, -1, &rect, DT_CALCRECT | DT_LEFT | DT_SINGLELINE);
552 if (!textheight && GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
553 {
554 win_skip( "DrawTextW not implemented\n" );
555 }
556 else
557 {
558 ok(textheight, "DrawTextW error %u\n", GetLastError());
559 ok(0 == rect.left, "expected 0, got %d\n", rect.left);
560 ok(0 == rect.right, "expected 0, got %d\n", rect.right);
561 ok(0 == rect.top, "expected 0, got %d\n", rect.top);
562 ok(rect.bottom, "rect.bottom should not be 0\n");
563 }
564
565 SelectObject(hdc, hOldFont);
566 ret = DeleteObject(hFont);
567 ok( ret, "DeleteObject error %u\n", GetLastError());
568
569 /* Clean up */
570 ret = ReleaseDC(hwnd, hdc);
571 ok( ret, "ReleaseDC error %u\n", GetLastError());
572 ret = DestroyWindow(hwnd);
573 ok( ret, "DestroyWindow error %u\n", GetLastError());
574 }
575
576 /* replace tabs by \t */
577 static void strfmt( const char *str, char *strout)
578 {
579 unsigned int i,j ;
580 for(i=0,j=0;i<=strlen(str);i++,j++)
581 if((strout[j]=str[i])=='\t') {
582 strout[j++]='\\';
583 strout[j]='t';
584 }
585 }
586
587
588 #define TABTEST( tabval, tabcount, string, _exp) \
589 { int i,x_act, x_exp; char strdisp[64];\
590 for(i=0;i<8;i++) tabs[i]=(i+1)*(tabval); \
591 extent = GetTabbedTextExtentA( hdc, string, strlen( string), (tabcount), tabs); \
592 strfmt( string, strdisp); \
593 /* trace( "Extent is %08lx\n", extent); */\
594 x_act = LOWORD( extent); \
595 x_exp = (_exp); \
596 ok( x_act == x_exp, "Test case \"%s\". Text extent is %d, expected %d tab %d tabcount %d\n", \
597 strdisp, x_act, x_exp, tabval, tabcount); \
598 } \
599
600
601 static void test_TabbedText(void)
602 {
603 HWND hwnd;
604 HDC hdc;
605 BOOL ret;
606 TEXTMETRICA tm;
607 DWORD extent;
608 INT tabs[8], cx, cy, tab, tabcount,t,align;
609
610 /* Initialization */
611 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
612 0, 0, 200, 200, 0, 0, 0, NULL);
613 ok(hwnd != 0, "CreateWindowExA error %u\n", GetLastError());
614 hdc = GetDC(hwnd);
615 ok(hdc != 0, "GetDC error %u\n", GetLastError());
616
617 ret = GetTextMetricsA( hdc, &tm);
618 ok( ret, "GetTextMetrics error %u\n", GetLastError());
619
620 extent = GetTabbedTextExtentA( hdc, "x", 1, 1, tabs);
621 cx = LOWORD( extent);
622 cy = HIWORD( extent);
623 trace( "cx is %d cy is %d\n", cx, cy);
624
625 align=1;
626 for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
627 catch the one off errors */
628 tab = (cx *4 + t);
629 /* test the special case tabcount =1 and the general array (80 of tabs */
630 for( tabcount = 1; tabcount <= 8; tabcount +=7) {
631 TABTEST( align * tab, tabcount, "\t", tab)
632 TABTEST( align * tab, tabcount, "xxx\t", tab)
633 TABTEST( align * tab, tabcount, "\tx", tab+cx)
634 TABTEST( align * tab, tabcount, "\t\t", tab*2)
635 TABTEST( align * tab, tabcount, "\tx\t", tab*2)
636 TABTEST( align * tab, tabcount, "x\tx", tab+cx)
637 TABTEST( align * tab, tabcount, "xx\tx", tab+cx)
638 TABTEST( align * tab, tabcount, "xxx\tx", tab+cx)
639 TABTEST( align * tab, tabcount, "xxxx\tx", t>0 ? tab + cx : 2*tab+cx)
640 TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab+cx)
641 }
642 }
643 align=-1;
644 for( t=-1; t<=1; t++) { /* slightly adjust the 4 char tabstop, to
645 catch the one off errors */
646 tab = (cx *4 + t);
647 /* test the special case tabcount =1 and the general array (8) of tabs */
648 for( tabcount = 1; tabcount <= 8; tabcount +=7) {
649 TABTEST( align * tab, tabcount, "\t", tab)
650 TABTEST( align * tab, tabcount, "xxx\t", tab)
651 TABTEST( align * tab, tabcount, "\tx", tab)
652 TABTEST( align * tab, tabcount, "\t\t", tab*2)
653 TABTEST( align * tab, tabcount, "\tx\t", tab*2)
654 TABTEST( align * tab, tabcount, "x\tx", tab)
655 TABTEST( align * tab, tabcount, "xx\tx", tab)
656 TABTEST( align * tab, tabcount, "xxx\tx", 4 * cx >= tab ? 2*tab :tab)
657 TABTEST( align * tab, tabcount, "xxxx\tx", 2*tab)
658 TABTEST( align * tab, tabcount, "xxxxx\tx", 2*tab)
659 }
660 }
661
662 ReleaseDC( hwnd, hdc );
663 DestroyWindow( hwnd );
664 }
665
666 static void test_DrawState(void)
667 {
668 static const char text[] = "Sample text string";
669 HWND hwnd;
670 HDC hdc;
671 BOOL ret;
672
673 hwnd = CreateWindowExA(0, "static", NULL, WS_POPUP,
674 0, 0, 200, 200, 0, 0, 0, NULL);
675 assert(hwnd);
676
677 hdc = GetDC(hwnd);
678 assert(hdc);
679
680 SetLastError(0xdeadbeef);
681 ret = DrawState(hdc, GetStockObject(DKGRAY_BRUSH), NULL, (LPARAM)text, strlen(text),
682 0, 0, 10, 10, DST_TEXT);
683 ok(ret, "DrawState error %u\n", GetLastError());
684
685 SetLastError(0xdeadbeef);
686 ret = DrawState(hdc, GetStockObject(DKGRAY_BRUSH), NULL, (LPARAM)text, 0,
687 0, 0, 10, 10, DST_TEXT);
688 ok(ret, "DrawState error %u\n", GetLastError());
689
690 SetLastError(0xdeadbeef);
691 ret = DrawState(hdc, GetStockObject(DKGRAY_BRUSH), NULL, 0, strlen(text),
692 0, 0, 10, 10, DST_TEXT);
693 ok(!ret || broken(ret) /* win98 */, "DrawState succeeded\n");
694 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
695
696 SetLastError(0xdeadbeef);
697 ret = DrawState(hdc, GetStockObject(DKGRAY_BRUSH), NULL, 0, 0,
698 0, 0, 10, 10, DST_TEXT);
699 ok(!ret || broken(ret) /* win98 */, "DrawState succeeded\n");
700 ok(GetLastError() == 0xdeadbeef, "not expected error %u\n", GetLastError());
701
702 ReleaseDC(hwnd, hdc);
703 DestroyWindow(hwnd);
704 }
705
706 START_TEST(text)
707 {
708 test_TabbedText();
709 test_DrawTextCalcRect();
710 test_DrawState();
711 }