1 /*
2  * Unit test suite for string format
3  *
4  * Copyright (C) 2007 Google (Evan Stade)
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19  */
20 
21 #include "objbase.h"
22 #include "gdiplus.h"
23 #include "wine/test.h"
24 
25 #define expect(expected, got) ok(got == expected, "Expected %.8x, got %.8x\n", expected, got)
26 #define expectf(expected, got) ok(got == expected, "Expected %.2f, got %.2f\n", expected, got)
27 
28 static void test_constructor(void)
29 {
30     GpStringFormat *format;
31     GpStatus stat;
32     INT n, count;
33     StringAlignment align, line_align;
34     StringTrimming trimming;
35     StringDigitSubstitute digitsub;
36     LANGID digitlang;
37 
38     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
39     expect(Ok, stat);
40 
41     GdipGetStringFormatAlign(format, &align);
42     GdipGetStringFormatLineAlign(format, &line_align);
43     GdipGetStringFormatHotkeyPrefix(format, &n);
44     GdipGetStringFormatTrimming(format, &trimming);
45     GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
46     GdipGetStringFormatMeasurableCharacterRangeCount(format, &count);
47 
48     expect(HotkeyPrefixNone, n);
49     expect(StringAlignmentNear, align);
50     expect(StringAlignmentNear, line_align);
51     expect(StringTrimmingCharacter, trimming);
52     expect(StringDigitSubstituteUser, digitsub);
53     expect(LANG_NEUTRAL, digitlang);
54     expect(0, count);
55 
56     stat = GdipDeleteStringFormat(format);
57     expect(Ok, stat);
58 }
59 
60 static void test_characterrange(void)
61 {
62     CharacterRange ranges[3];
63     INT count;
64     GpStringFormat* format;
65     GpStatus stat;
66 
67     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
68     expect(Ok, stat);
69     stat = GdipSetStringFormatMeasurableCharacterRanges(NULL, 3, ranges);
70     expect(InvalidParameter, stat);
71     stat = GdipSetStringFormatMeasurableCharacterRanges(format, 0, ranges);
72     expect(Ok, stat);
73     stat = GdipSetStringFormatMeasurableCharacterRanges(format, 3, NULL);
74     expect(InvalidParameter, stat);
75 
76     stat = GdipSetStringFormatMeasurableCharacterRanges(format, 3, ranges);
77     expect(Ok, stat);
78     stat = GdipGetStringFormatMeasurableCharacterRangeCount(format, &count);
79     expect(Ok, stat);
80     if (stat == Ok) expect(3, count);
81 
82     stat= GdipDeleteStringFormat(format);
83     expect(Ok, stat);
84 }
85 
86 static void test_digitsubstitution(void)
87 {
88     GpStringFormat *format;
89     GpStatus stat;
90     StringDigitSubstitute digitsub;
91     LANGID digitlang;
92 
93     stat = GdipCreateStringFormat(0, LANG_RUSSIAN, &format);
94     expect(Ok, stat);
95 
96     /* NULL arguments */
97     stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, NULL);
98     expect(InvalidParameter, stat);
99     stat = GdipGetStringFormatDigitSubstitution(format, NULL, NULL);
100     expect(Ok, stat);
101     stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, NULL);
102     expect(InvalidParameter, stat);
103     stat = GdipGetStringFormatDigitSubstitution(NULL, NULL, &digitsub);
104     expect(InvalidParameter, stat);
105     stat = GdipGetStringFormatDigitSubstitution(NULL, &digitlang, &digitsub);
106     expect(InvalidParameter, stat);
107     stat = GdipSetStringFormatDigitSubstitution(NULL, LANG_NEUTRAL, StringDigitSubstituteNone);
108     expect(InvalidParameter, stat);
109 
110     /* try to get both and one by one */
111     stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
112     expect(Ok, stat);
113     expect(StringDigitSubstituteUser, digitsub);
114     expect(LANG_NEUTRAL, digitlang);
115 
116     digitsub  = StringDigitSubstituteNone;
117     stat = GdipGetStringFormatDigitSubstitution(format, NULL, &digitsub);
118     expect(Ok, stat);
119     expect(StringDigitSubstituteUser, digitsub);
120 
121     digitlang = LANG_RUSSIAN;
122     stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, NULL);
123     expect(Ok, stat);
124     expect(LANG_NEUTRAL, digitlang);
125 
126     /* set/get */
127     stat = GdipSetStringFormatDigitSubstitution(format, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL),
128                                                         StringDigitSubstituteUser);
129     expect(Ok, stat);
130     digitsub  = StringDigitSubstituteNone;
131     digitlang = LANG_RUSSIAN;
132     stat = GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
133     expect(Ok, stat);
134     expect(StringDigitSubstituteUser, digitsub);
135     expect(MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_TRADITIONAL), digitlang);
136 
137     stat = GdipDeleteStringFormat(format);
138     expect(Ok, stat);
139 }
140 
141 static void test_getgenerictypographic(void)
142 {
143     GpStringFormat *format, *format2;
144     GpStatus stat;
145     INT flags;
146     INT n;
147     StringAlignment align, line_align;
148     StringTrimming trimming;
149     StringDigitSubstitute digitsub;
150     LANGID digitlang;
151     INT tabcount;
152 
153     /* NULL arg */
154     stat = GdipStringFormatGetGenericTypographic(NULL);
155     expect(InvalidParameter, stat);
156 
157     stat = GdipStringFormatGetGenericTypographic(&format);
158     expect(Ok, stat);
159 
160     stat = GdipStringFormatGetGenericTypographic(&format2);
161     expect(Ok, stat);
162     ok(format == format2, "expected same format object\n");
163     stat = GdipDeleteStringFormat(format2);
164     expect(Ok, stat);
165 
166     GdipGetStringFormatFlags(format, &flags);
167     GdipGetStringFormatAlign(format, &align);
168     GdipGetStringFormatLineAlign(format, &line_align);
169     GdipGetStringFormatHotkeyPrefix(format, &n);
170     GdipGetStringFormatTrimming(format, &trimming);
171     GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
172     GdipGetStringFormatTabStopCount(format, &tabcount);
173 
174     expect((StringFormatFlagsNoFitBlackBox |StringFormatFlagsLineLimit | StringFormatFlagsNoClip),
175             flags);
176     expect(HotkeyPrefixNone, n);
177     expect(StringAlignmentNear, align);
178     expect(StringAlignmentNear, line_align);
179     expect(StringTrimmingNone, trimming);
180     expect(StringDigitSubstituteUser, digitsub);
181     expect(LANG_NEUTRAL, digitlang);
182     expect(0, tabcount);
183 
184     /* Change format parameters, release, get format object again. */
185     stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap);
186     expect(Ok, stat);
187 
188     stat = GdipGetStringFormatFlags(format, &flags);
189     expect(Ok, stat);
190     expect(StringFormatFlagsNoWrap, flags);
191 
192     stat = GdipDeleteStringFormat(format);
193     expect(Ok, stat);
194 
195     stat = GdipStringFormatGetGenericTypographic(&format);
196     expect(Ok, stat);
197 
198     stat = GdipGetStringFormatFlags(format, &flags);
199     expect(Ok, stat);
200     expect(StringFormatFlagsNoWrap, flags);
201 
202     stat = GdipDeleteStringFormat(format);
203     expect(Ok, stat);
204 }
205 
206 static REAL tabstops[] = {0.0, 10.0, 2.0};
207 static void test_tabstops(void)
208 {
209     GpStringFormat *format;
210     GpStatus stat;
211     INT count;
212     REAL tabs[3];
213     REAL firsttab;
214 
215     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
216     expect(Ok, stat);
217 
218     /* NULL */
219     stat = GdipGetStringFormatTabStopCount(NULL, NULL);
220     expect(InvalidParameter, stat);
221     stat = GdipGetStringFormatTabStopCount(NULL, &count);
222     expect(InvalidParameter, stat);
223     stat = GdipGetStringFormatTabStopCount(format, NULL);
224     expect(InvalidParameter, stat);
225 
226     stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, NULL);
227     expect(InvalidParameter, stat);
228     stat = GdipSetStringFormatTabStops(format, 0.0, 0, NULL);
229     expect(InvalidParameter, stat);
230     stat = GdipSetStringFormatTabStops(NULL, 0.0, 0, tabstops);
231     expect(InvalidParameter, stat);
232 
233     stat = GdipGetStringFormatTabStops(NULL, 0, NULL, NULL);
234     expect(InvalidParameter, stat);
235     stat = GdipGetStringFormatTabStops(format, 0, NULL, NULL);
236     expect(InvalidParameter, stat);
237     stat = GdipGetStringFormatTabStops(NULL, 0, &firsttab, NULL);
238     expect(InvalidParameter, stat);
239     stat = GdipGetStringFormatTabStops(NULL, 0, NULL, tabs);
240     expect(InvalidParameter, stat);
241     stat = GdipGetStringFormatTabStops(format, 0, &firsttab, NULL);
242     expect(InvalidParameter, stat);
243     stat = GdipGetStringFormatTabStops(format, 0, NULL, tabs);
244     expect(InvalidParameter, stat);
245 
246     /* not NULL */
247     stat = GdipGetStringFormatTabStopCount(format, &count);
248     expect(Ok, stat);
249     expect(0, count);
250     /* negative tabcount */
251     stat = GdipSetStringFormatTabStops(format, 0.0, -1, tabstops);
252     expect(Ok, stat);
253     count = -1;
254     stat = GdipGetStringFormatTabStopCount(format, &count);
255     expect(Ok, stat);
256     expect(0, count);
257 
258     stat = GdipSetStringFormatTabStops(format, -10.0, 0, tabstops);
259     expect(Ok, stat);
260     stat = GdipSetStringFormatTabStops(format, -10.0, 1, tabstops);
261     expect(NotImplemented, stat);
262 
263     firsttab = -1.0;
264     tabs[0] = tabs[1] = tabs[2] = -1.0;
265     stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs);
266     expect(Ok, stat);
267     expectf(-1.0, tabs[0]);
268     expectf(-1.0, tabs[1]);
269     expectf(-1.0, tabs[2]);
270     expectf(0.0, firsttab);
271 
272     stat = GdipSetStringFormatTabStops(format, +0.0, 3, tabstops);
273     expect(Ok, stat);
274     count = 0;
275     stat = GdipGetStringFormatTabStopCount(format, &count);
276     expect(Ok, stat);
277     expect(3, count);
278 
279     firsttab = -1.0;
280     tabs[0] = tabs[1] = tabs[2] = -1.0;
281     stat = GdipGetStringFormatTabStops(format, 3, &firsttab, tabs);
282     expect(Ok, stat);
283     expectf(0.0,  tabs[0]);
284     expectf(10.0, tabs[1]);
285     expectf(2.0,  tabs[2]);
286     expectf(0.0,  firsttab);
287 
288     stat = GdipSetStringFormatTabStops(format, 10.0, 3, tabstops);
289     expect(Ok, stat);
290     firsttab = -1.0;
291     tabs[0] = tabs[1] = tabs[2] = -1.0;
292     stat = GdipGetStringFormatTabStops(format, 0, &firsttab, tabs);
293     expect(Ok, stat);
294     expectf(-1.0, tabs[0]);
295     expectf(-1.0, tabs[1]);
296     expectf(-1.0, tabs[2]);
297     expectf(10.0, firsttab);
298 
299     /* zero tabcount, after valid setting to 3 */
300     stat = GdipSetStringFormatTabStops(format, 0.0, 0, tabstops);
301     expect(Ok, stat);
302     count = 0;
303     stat = GdipGetStringFormatTabStopCount(format, &count);
304     expect(Ok, stat);
305     expect(3, count);
306 
307     stat = GdipDeleteStringFormat(format);
308     expect(Ok, stat);
309 }
310 
311 static void test_getgenericdefault(void)
312 {
313     GpStringFormat *format, *format2;
314     GpStatus stat;
315 
316     INT flags;
317     INT n;
318     StringAlignment align, line_align;
319     StringTrimming trimming;
320     StringDigitSubstitute digitsub;
321     LANGID digitlang;
322     INT tabcount;
323 
324     /* NULL arg */
325     stat = GdipStringFormatGetGenericDefault(NULL);
326     expect(InvalidParameter, stat);
327 
328     stat = GdipStringFormatGetGenericDefault(&format);
329     expect(Ok, stat);
330 
331     stat = GdipStringFormatGetGenericDefault(&format2);
332     expect(Ok, stat);
333     ok(format == format2, "expected same format object\n");
334     stat = GdipDeleteStringFormat(format2);
335     expect(Ok, stat);
336 
337     GdipGetStringFormatFlags(format, &flags);
338     GdipGetStringFormatAlign(format, &align);
339     GdipGetStringFormatLineAlign(format, &line_align);
340     GdipGetStringFormatHotkeyPrefix(format, &n);
341     GdipGetStringFormatTrimming(format, &trimming);
342     GdipGetStringFormatDigitSubstitution(format, &digitlang, &digitsub);
343     GdipGetStringFormatTabStopCount(format, &tabcount);
344 
345     expect(0, flags);
346     expect(HotkeyPrefixNone, n);
347     expect(StringAlignmentNear, align);
348     expect(StringAlignmentNear, line_align);
349     expect(StringTrimmingCharacter, trimming);
350     expect(StringDigitSubstituteUser, digitsub);
351     expect(LANG_NEUTRAL, digitlang);
352     expect(0, tabcount);
353 
354     /* Change default format parameters, release, get format object again. */
355     stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoWrap);
356     expect(Ok, stat);
357 
358     stat = GdipGetStringFormatFlags(format, &flags);
359     expect(Ok, stat);
360     expect(StringFormatFlagsNoWrap, flags);
361 
362     stat = GdipDeleteStringFormat(format);
363     expect(Ok, stat);
364 
365     stat = GdipStringFormatGetGenericDefault(&format);
366     expect(Ok, stat);
367 
368     stat = GdipGetStringFormatFlags(format, &flags);
369     expect(Ok, stat);
370     expect(StringFormatFlagsNoWrap, flags);
371 
372     stat = GdipDeleteStringFormat(format);
373     expect(Ok, stat);
374 }
375 
376 static void test_stringformatflags(void)
377 {
378     GpStringFormat *format;
379     GpStatus stat;
380 
381     INT flags;
382 
383     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, &format);
384     expect(Ok, stat);
385 
386     /* NULL args */
387     stat = GdipSetStringFormatFlags(NULL, 0);
388     expect(InvalidParameter, stat);
389 
390     stat = GdipSetStringFormatFlags(format, 0);
391     expect(Ok, stat);
392     stat = GdipGetStringFormatFlags(format, &flags);
393     expect(Ok, stat);
394     expect(0, flags);
395 
396     /* Check some valid flags */
397     stat = GdipSetStringFormatFlags(format, StringFormatFlagsDirectionRightToLeft);
398     expect(Ok, stat);
399     stat = GdipGetStringFormatFlags(format, &flags);
400     expect(Ok, stat);
401     expect(StringFormatFlagsDirectionRightToLeft, flags);
402 
403     stat = GdipSetStringFormatFlags(format, StringFormatFlagsNoFontFallback);
404     expect(Ok, stat);
405     stat = GdipGetStringFormatFlags(format, &flags);
406     expect(Ok, stat);
407     expect(StringFormatFlagsNoFontFallback, flags);
408 
409     /* Check some flag combinations */
410     stat = GdipSetStringFormatFlags(format, StringFormatFlagsDirectionVertical
411         | StringFormatFlagsNoFitBlackBox);
412     expect(Ok, stat);
413     stat = GdipGetStringFormatFlags(format, &flags);
414     expect(Ok, stat);
415     expect((StringFormatFlagsDirectionVertical
416         | StringFormatFlagsNoFitBlackBox), flags);
417 
418     stat = GdipSetStringFormatFlags(format, StringFormatFlagsDisplayFormatControl
419         | StringFormatFlagsMeasureTrailingSpaces);
420     expect(Ok, stat);
421     stat = GdipGetStringFormatFlags(format, &flags);
422     expect(Ok, stat);
423     expect((StringFormatFlagsDisplayFormatControl
424         | StringFormatFlagsMeasureTrailingSpaces), flags);
425 
426     /* Check invalid flags */
427     stat = GdipSetStringFormatFlags(format, 0xdeadbeef);
428     expect(Ok, stat);
429     stat = GdipGetStringFormatFlags(format, &flags);
430     expect(Ok, stat);
431     expect(0xdeadbeef, flags);
432 
433     stat = GdipDeleteStringFormat(format);
434     expect(Ok, stat);
435 }
436 
437 START_TEST(stringformat)
438 {
439     struct GdiplusStartupInput gdiplusStartupInput;
440     ULONG_PTR gdiplusToken;
441     HMODULE hmsvcrt;
442     int (CDECL * _controlfp_s)(unsigned int *cur, unsigned int newval, unsigned int mask);
443 
444     /* Enable all FP exceptions except _EM_INEXACT, which gdi32 can trigger */
445     hmsvcrt = LoadLibraryA("msvcrt");
446     _controlfp_s = (void*)GetProcAddress(hmsvcrt, "_controlfp_s");
447     if (_controlfp_s) _controlfp_s(0, 0, 0x0008001e);
448 
449     gdiplusStartupInput.GdiplusVersion              = 1;
450     gdiplusStartupInput.DebugEventCallback          = NULL;
451     gdiplusStartupInput.SuppressBackgroundThread    = 0;
452     gdiplusStartupInput.SuppressExternalCodecs      = 0;
453 
454     GdiplusStartup(&gdiplusToken, &gdiplusStartupInput, NULL);
455 
456     test_constructor();
457     test_characterrange();
458     test_digitsubstitution();
459     test_getgenerictypographic();
460     test_tabstops();
461     test_getgenericdefault();
462     test_stringformatflags();
463 
464     GdiplusShutdown(gdiplusToken);
465 }
466