twain_32: Change get requirements such that we require only a minimum level of support.
[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     if(!format)
39         return InvalidParameter;
40
41     *format = GdipAlloc(sizeof(GpStringFormat));
42     if(!*format)   return OutOfMemory;
43
44     (*format)->attr = attr;
45     (*format)->lang = lang;
46     (*format)->digitlang = LANG_NEUTRAL;
47     (*format)->trimming = StringTrimmingCharacter;
48     (*format)->digitsub = StringDigitSubstituteUser;
49     /* tabstops */
50     (*format)->tabcount = 0;
51     (*format)->firsttab = 0.0;
52     (*format)->tabs = NULL;
53
54     return Ok;
55 }
56
57 GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
58 {
59     if(!format)
60         return InvalidParameter;
61
62     GdipFree(format->tabs);
63     GdipFree(format);
64
65     return Ok;
66 }
67
68 GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
69 {
70     GpStatus stat;
71
72     if (!format)
73         return InvalidParameter;
74
75     stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format);
76     if(stat != Ok)
77         return stat;
78
79     (*format)->align     = StringAlignmentNear;
80     (*format)->vertalign = StringAlignmentNear;
81
82     return Ok;
83 }
84
85 GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format,
86     StringAlignment *align)
87 {
88     if(!format || !align)
89         return InvalidParameter;
90
91     *align = format->align;
92
93     return Ok;
94 }
95
96 GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat *format,
97     LANGID *language, StringDigitSubstitute *substitute)
98 {
99     if(!format)
100         return InvalidParameter;
101
102     if(language)    *language   = format->digitlang;
103     if(substitute)  *substitute = format->digitsub;
104
105     return Ok;
106 }
107
108 GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat* format,
109         INT* flags)
110 {
111     if (!(format && flags))
112         return InvalidParameter;
113
114     *flags = format->attr;
115
116     return Ok;
117 }
118
119 GpStatus WINGDIPAPI GdipGetStringFormatHotkeyPrefix(GDIPCONST GpStringFormat
120     *format, INT *hkpx)
121 {
122     if(!format || !hkpx)
123         return InvalidParameter;
124
125     *hkpx = (INT)format->hkprefix;
126
127     return Ok;
128 }
129
130 GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format,
131     StringAlignment *align)
132 {
133     if(!format || !align)
134         return InvalidParameter;
135
136     *align = format->vertalign;
137
138     return Ok;
139 }
140
141 GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount(
142         GDIPCONST GpStringFormat* format, INT* count)
143 {
144     if (!(format && count))
145         return InvalidParameter;
146
147     FIXME("stub: %p %p\n", format, count);
148
149     return NotImplemented;
150 }
151
152 GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat *format,
153     INT *count)
154 {
155     if(!format || !count)
156         return InvalidParameter;
157
158     *count = format->tabcount;
159
160     return Ok;
161 }
162
163 GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat *format, INT count,
164     REAL *firsttab, REAL *tabs)
165 {
166     if(!format || !firsttab || !tabs)
167         return InvalidParameter;
168
169     /* native simply crashes on count < 0 */
170     if(count != 0)
171         memcpy(tabs, format->tabs, sizeof(REAL)*count);
172
173     *firsttab = format->firsttab;
174
175     return Ok;
176 }
177
178 GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat *format,
179     StringTrimming *trimming)
180 {
181     if(!format || !trimming)
182         return InvalidParameter;
183
184     *trimming = format->trimming;
185
186     return Ok;
187 }
188
189 GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat *format,
190     StringAlignment align)
191 {
192     if(!format)
193         return InvalidParameter;
194
195     format->align = align;
196
197     return Ok;
198 }
199
200 /*FIXME: digit substitution actually not implemented, get/set only */
201 GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat *format,
202     LANGID language, StringDigitSubstitute substitute)
203 {
204     if(!format)
205         return InvalidParameter;
206
207     format->digitlang = language;
208     format->digitsub  = substitute;
209
210     return Ok;
211 }
212
213 GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat *format,
214     INT hkpx)
215 {
216     if(!format || hkpx < 0 || hkpx > 2)
217         return InvalidParameter;
218
219     format->hkprefix = (HotkeyPrefix) hkpx;
220
221     return Ok;
222 }
223
224 GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format,
225     StringAlignment align)
226 {
227     if(!format)
228         return InvalidParameter;
229
230     format->vertalign = align;
231
232     return Ok;
233 }
234
235 GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges(GpStringFormat*
236         format, INT rangeCount, GDIPCONST CharacterRange* ranges)
237 {
238     if (!(format && rangeCount && ranges))
239         return InvalidParameter;
240
241     FIXME("stub: %p, %d, %p\n", format, rangeCount, ranges);
242
243     return NotImplemented;
244 }
245
246 GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat *format, REAL firsttab,
247     INT count, GDIPCONST REAL *tabs)
248 {
249     if(!format || !tabs)
250         return InvalidParameter;
251
252     if(count > 0){
253         if(firsttab < 0.0)  return NotImplemented;
254         /* first time allocation */
255         if(format->tabcount == 0){
256             format->tabs = GdipAlloc(sizeof(REAL)*count);
257             if(!format->tabs)
258                 return OutOfMemory;
259         }
260         /* reallocation */
261         if((format->tabcount < count) && (format->tabcount > 0)){
262             REAL *ptr;
263             ptr = HeapReAlloc(GetProcessHeap(), 0, format->tabs, sizeof(REAL)*count);
264             if(!ptr)
265                 return OutOfMemory;
266             format->tabs = ptr;
267         }
268         format->firsttab = firsttab;
269         format->tabcount = count;
270         memcpy(format->tabs, tabs, sizeof(REAL)*count);
271     }
272
273     return Ok;
274 }
275
276 GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format,
277     StringTrimming trimming)
278 {
279     if(!format)
280         return InvalidParameter;
281
282     format->trimming = trimming;
283
284     return Ok;
285 }
286
287 GpStatus WINGDIPAPI GdipSetStringFormatFlags(GpStringFormat *format, INT flags)
288 {
289     if(!format)
290         return InvalidParameter;
291
292     format->attr = flags;
293
294     return Ok;
295 }
296
297 GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat)
298 {
299     if(!format || !newFormat)
300         return InvalidParameter;
301
302     *newFormat = GdipAlloc(sizeof(GpStringFormat));
303     if(!*newFormat)    return OutOfMemory;
304
305     **newFormat = *format;
306
307     if(format->tabcount > 0){
308         (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount);
309         if(!(*newFormat)->tabs){
310             GdipFree(*newFormat);
311             return OutOfMemory;
312         }
313         memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount);
314     }
315     else
316         (*newFormat)->tabs = NULL;
317
318     TRACE("%p %p\n",format,newFormat);
319
320     return Ok;
321 }
322
323 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
324 {
325     GpStatus stat;
326
327     if(!format)
328         return InvalidParameter;
329
330     stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox |
331                                   StringFormatFlagsLineLimit |
332                                   StringFormatFlagsNoClip, LANG_NEUTRAL, format);
333     if(stat != Ok)
334         return stat;
335
336     (*format)->digitlang = LANG_NEUTRAL;
337     (*format)->digitsub  = StringDigitSubstituteUser;
338     (*format)->trimming  = StringTrimmingNone;
339     (*format)->hkprefix  = HotkeyPrefixNone;
340     (*format)->align     = StringAlignmentNear;
341     (*format)->vertalign = StringAlignmentNear;
342
343     return Ok;
344 }