cryptui: Avoid signed-unsigned integer comparisons.
[wine] / dlls / gdiplus / stringformat.c
1 /*
2  *
3  * Copyright (C) 2007 Google (Evan Stade)
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
18  */
19
20 #include <stdarg.h>
21
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wingdi.h"
25 #include "winnls.h"
26
27 #include "objbase.h"
28
29 #include "gdiplus.h"
30 #include "gdiplus_private.h"
31 #include "wine/debug.h"
32
33 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
34
35 GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
36     GpStringFormat **format)
37 {
38     TRACE("(%i, %x, %p)\n", attr, lang, format);
39
40     if(!format)
41         return InvalidParameter;
42
43     *format = GdipAlloc(sizeof(GpStringFormat));
44     if(!*format)   return OutOfMemory;
45
46     (*format)->attr = attr;
47     (*format)->lang = lang;
48     (*format)->digitlang = LANG_NEUTRAL;
49     (*format)->trimming = StringTrimmingCharacter;
50     (*format)->digitsub = StringDigitSubstituteUser;
51     (*format)->character_ranges = NULL;
52     (*format)->range_count = 0;
53     (*format)->generic_typographic = FALSE;
54     /* tabstops */
55     (*format)->tabcount = 0;
56     (*format)->firsttab = 0.0;
57     (*format)->tabs = NULL;
58
59     TRACE("<-- %p\n", *format);
60
61     return Ok;
62 }
63
64 GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
65 {
66     if(!format)
67         return InvalidParameter;
68
69     GdipFree(format->character_ranges);
70     GdipFree(format->tabs);
71     GdipFree(format);
72
73     return Ok;
74 }
75
76 GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
77 {
78     GpStatus stat;
79
80     if (!format)
81         return InvalidParameter;
82
83     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format);
84     if(stat != Ok)
85         return stat;
86
87     (*format)->align     = StringAlignmentNear;
88     (*format)->vertalign = StringAlignmentNear;
89
90     return Ok;
91 }
92
93 GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format,
94     StringAlignment *align)
95 {
96     if(!format || !align)
97         return InvalidParameter;
98
99     *align = format->align;
100
101     return Ok;
102 }
103
104 GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat *format,
105     LANGID *language, StringDigitSubstitute *substitute)
106 {
107     if(!format)
108         return InvalidParameter;
109
110     if(language)    *language   = format->digitlang;
111     if(substitute)  *substitute = format->digitsub;
112
113     return Ok;
114 }
115
116 GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat* format,
117         INT* flags)
118 {
119     if (!(format && flags))
120         return InvalidParameter;
121
122     *flags = format->attr;
123
124     return Ok;
125 }
126
127 GpStatus WINGDIPAPI GdipGetStringFormatHotkeyPrefix(GDIPCONST GpStringFormat
128     *format, INT *hkpx)
129 {
130     if(!format || !hkpx)
131         return InvalidParameter;
132
133     *hkpx = (INT)format->hkprefix;
134
135     return Ok;
136 }
137
138 GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format,
139     StringAlignment *align)
140 {
141     if(!format || !align)
142         return InvalidParameter;
143
144     *align = format->vertalign;
145
146     return Ok;
147 }
148
149 GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount(
150     GDIPCONST GpStringFormat *format, INT *count)
151 {
152     if (!(format && count))
153         return InvalidParameter;
154
155     TRACE("%p %p\n", format, count);
156
157     *count = format->range_count;
158
159     return Ok;
160 }
161
162 GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat *format,
163     INT *count)
164 {
165     if(!format || !count)
166         return InvalidParameter;
167
168     *count = format->tabcount;
169
170     return Ok;
171 }
172
173 GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat *format, INT count,
174     REAL *firsttab, REAL *tabs)
175 {
176     if(!format || !firsttab || !tabs)
177         return InvalidParameter;
178
179     /* native simply crashes on count < 0 */
180     if(count != 0)
181         memcpy(tabs, format->tabs, sizeof(REAL)*count);
182
183     *firsttab = format->firsttab;
184
185     return Ok;
186 }
187
188 GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat *format,
189     StringTrimming *trimming)
190 {
191     if(!format || !trimming)
192         return InvalidParameter;
193
194     *trimming = format->trimming;
195
196     return Ok;
197 }
198
199 GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat *format,
200     StringAlignment align)
201 {
202     TRACE("(%p, %i)\n", format, align);
203
204     if(!format)
205         return InvalidParameter;
206
207     format->align = align;
208
209     return Ok;
210 }
211
212 /*FIXME: digit substitution actually not implemented, get/set only */
213 GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat *format,
214     LANGID language, StringDigitSubstitute substitute)
215 {
216     TRACE("(%p, %x, %i)\n", format, language, substitute);
217
218     if(!format)
219         return InvalidParameter;
220
221     format->digitlang = language;
222     format->digitsub  = substitute;
223
224     return Ok;
225 }
226
227 GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat *format,
228     INT hkpx)
229 {
230     TRACE("(%p, %i)\n", format, hkpx);
231
232     if(!format || hkpx < 0 || hkpx > 2)
233         return InvalidParameter;
234
235     format->hkprefix = (HotkeyPrefix) hkpx;
236
237     return Ok;
238 }
239
240 GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format,
241     StringAlignment align)
242 {
243     TRACE("(%p, %i)\n", format, align);
244
245     if(!format)
246         return InvalidParameter;
247
248     format->vertalign = align;
249
250     return Ok;
251 }
252
253 GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges(
254     GpStringFormat *format, INT rangeCount, GDIPCONST CharacterRange *ranges)
255 {
256     CharacterRange *new_ranges;
257
258     if (!(format && ranges))
259         return InvalidParameter;
260
261     TRACE("%p, %d, %p\n", format, rangeCount, ranges);
262
263     new_ranges = GdipAlloc(rangeCount * sizeof(CharacterRange));
264     if (!new_ranges)
265         return OutOfMemory;
266
267     GdipFree(format->character_ranges);
268     format->character_ranges = new_ranges;
269     memcpy(format->character_ranges, ranges, sizeof(CharacterRange) * rangeCount);
270     format->range_count = rangeCount;
271
272     return Ok;
273 }
274
275 GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat *format, REAL firsttab,
276     INT count, GDIPCONST REAL *tabs)
277 {
278     TRACE("(%p, %0.2f, %i, %p)\n", format, firsttab, count, tabs);
279
280     if(!format || !tabs)
281         return InvalidParameter;
282
283     if(count > 0){
284         if(firsttab < 0.0)  return NotImplemented;
285         /* first time allocation */
286         if(format->tabcount == 0){
287             format->tabs = GdipAlloc(sizeof(REAL)*count);
288             if(!format->tabs)
289                 return OutOfMemory;
290         }
291         /* reallocation */
292         if((format->tabcount < count) && (format->tabcount > 0)){
293             REAL *ptr;
294             ptr = HeapReAlloc(GetProcessHeap(), 0, format->tabs, sizeof(REAL)*count);
295             if(!ptr)
296                 return OutOfMemory;
297             format->tabs = ptr;
298         }
299         format->firsttab = firsttab;
300         format->tabcount = count;
301         memcpy(format->tabs, tabs, sizeof(REAL)*count);
302     }
303
304     return Ok;
305 }
306
307 GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format,
308     StringTrimming trimming)
309 {
310     TRACE("(%p, %i)\n", format, trimming);
311
312     if(!format)
313         return InvalidParameter;
314
315     format->trimming = trimming;
316
317     return Ok;
318 }
319
320 GpStatus WINGDIPAPI GdipSetStringFormatFlags(GpStringFormat *format, INT flags)
321 {
322     TRACE("(%p, %x)\n", format, flags);
323
324     if(!format)
325         return InvalidParameter;
326
327     format->attr = flags;
328
329     return Ok;
330 }
331
332 GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat)
333 {
334     if(!format || !newFormat)
335         return InvalidParameter;
336
337     *newFormat = GdipAlloc(sizeof(GpStringFormat));
338     if(!*newFormat)    return OutOfMemory;
339
340     **newFormat = *format;
341
342     if(format->tabcount > 0){
343         (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount);
344         if(!(*newFormat)->tabs){
345             GdipFree(*newFormat);
346             return OutOfMemory;
347         }
348         memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount);
349     }
350     else
351         (*newFormat)->tabs = NULL;
352
353     if(format->range_count > 0){
354         (*newFormat)->character_ranges = GdipAlloc(sizeof(CharacterRange) * format->range_count);
355         if(!(*newFormat)->character_ranges){
356             GdipFree((*newFormat)->tabs);
357             GdipFree(*newFormat);
358             return OutOfMemory;
359         }
360         memcpy((*newFormat)->character_ranges, format->character_ranges,
361                sizeof(CharacterRange) * format->range_count);
362     }
363     else
364         (*newFormat)->character_ranges = NULL;
365
366     TRACE("%p %p\n",format,newFormat);
367
368     return Ok;
369 }
370
371 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
372 {
373     GpStatus stat;
374
375     if(!format)
376         return InvalidParameter;
377
378     stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox |
379                                   StringFormatFlagsLineLimit |
380                                   StringFormatFlagsNoClip, LANG_NEUTRAL, format);
381     if(stat != Ok)
382         return stat;
383
384     (*format)->digitlang = LANG_NEUTRAL;
385     (*format)->digitsub  = StringDigitSubstituteUser;
386     (*format)->trimming  = StringTrimmingNone;
387     (*format)->hkprefix  = HotkeyPrefixNone;
388     (*format)->align     = StringAlignmentNear;
389     (*format)->vertalign = StringAlignmentNear;
390     (*format)->generic_typographic = TRUE;
391
392     TRACE("%p => %p\n", format, *format);
393
394     return Ok;
395 }