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