msacm32/tests: Allow alternative product id.
[wine.git] / dlls / gdiplus / stringformat.c
blob7d6bcb0e3fb8334c0205383f17eeebb2ae717d5e
1 /*
3 * Copyright (C) 2007 Google (Evan Stade)
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.
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.
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
20 #include <stdarg.h>
22 #include "windef.h"
23 #include "winbase.h"
24 #include "wingdi.h"
25 #include "winnls.h"
27 #include "objbase.h"
29 #include "gdiplus.h"
30 #include "gdiplus_private.h"
31 #include "wine/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(gdiplus);
35 GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
36 GpStringFormat **format)
38 TRACE("(%i, %x, %p)\n", attr, lang, format);
40 if(!format)
41 return InvalidParameter;
43 *format = GdipAlloc(sizeof(GpStringFormat));
44 if(!*format) return OutOfMemory;
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;
59 TRACE("<-- %p\n", *format);
61 return Ok;
64 GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
66 if(!format)
67 return InvalidParameter;
69 GdipFree(format->character_ranges);
70 GdipFree(format->tabs);
71 GdipFree(format);
73 return Ok;
76 GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
78 GpStatus stat;
80 if (!format)
81 return InvalidParameter;
83 stat = GdipCreateStringFormat(0, LANG_NEUTRAL, format);
84 if(stat != Ok)
85 return stat;
87 (*format)->align = StringAlignmentNear;
88 (*format)->vertalign = StringAlignmentNear;
90 return Ok;
93 GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format,
94 StringAlignment *align)
96 if(!format || !align)
97 return InvalidParameter;
99 *align = format->align;
101 return Ok;
104 GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat *format,
105 LANGID *language, StringDigitSubstitute *substitute)
107 if(!format)
108 return InvalidParameter;
110 if(language) *language = format->digitlang;
111 if(substitute) *substitute = format->digitsub;
113 return Ok;
116 GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat* format,
117 INT* flags)
119 if (!(format && flags))
120 return InvalidParameter;
122 *flags = format->attr;
124 return Ok;
127 GpStatus WINGDIPAPI GdipGetStringFormatHotkeyPrefix(GDIPCONST GpStringFormat
128 *format, INT *hkpx)
130 if(!format || !hkpx)
131 return InvalidParameter;
133 *hkpx = (INT)format->hkprefix;
135 return Ok;
138 GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format,
139 StringAlignment *align)
141 if(!format || !align)
142 return InvalidParameter;
144 *align = format->vertalign;
146 return Ok;
149 GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount(
150 GDIPCONST GpStringFormat *format, INT *count)
152 if (!(format && count))
153 return InvalidParameter;
155 TRACE("%p %p\n", format, count);
157 *count = format->range_count;
159 return Ok;
162 GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat *format,
163 INT *count)
165 if(!format || !count)
166 return InvalidParameter;
168 *count = format->tabcount;
170 return Ok;
173 GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat *format, INT count,
174 REAL *firsttab, REAL *tabs)
176 if(!format || !firsttab || !tabs)
177 return InvalidParameter;
179 /* native simply crashes on count < 0 */
180 if(count != 0)
181 memcpy(tabs, format->tabs, sizeof(REAL)*count);
183 *firsttab = format->firsttab;
185 return Ok;
188 GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat *format,
189 StringTrimming *trimming)
191 if(!format || !trimming)
192 return InvalidParameter;
194 *trimming = format->trimming;
196 return Ok;
199 GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat *format,
200 StringAlignment align)
202 TRACE("(%p, %i)\n", format, align);
204 if(!format)
205 return InvalidParameter;
207 format->align = align;
209 return Ok;
212 /*FIXME: digit substitution actually not implemented, get/set only */
213 GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat *format,
214 LANGID language, StringDigitSubstitute substitute)
216 TRACE("(%p, %x, %i)\n", format, language, substitute);
218 if(!format)
219 return InvalidParameter;
221 format->digitlang = language;
222 format->digitsub = substitute;
224 return Ok;
227 GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat *format,
228 INT hkpx)
230 TRACE("(%p, %i)\n", format, hkpx);
232 if(!format || hkpx < 0 || hkpx > 2)
233 return InvalidParameter;
235 format->hkprefix = (HotkeyPrefix) hkpx;
237 return Ok;
240 GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format,
241 StringAlignment align)
243 TRACE("(%p, %i)\n", format, align);
245 if(!format)
246 return InvalidParameter;
248 format->vertalign = align;
250 return Ok;
253 GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges(
254 GpStringFormat *format, INT rangeCount, GDIPCONST CharacterRange *ranges)
256 CharacterRange *new_ranges;
258 if (!(format && ranges))
259 return InvalidParameter;
261 TRACE("%p, %d, %p\n", format, rangeCount, ranges);
263 new_ranges = GdipAlloc(rangeCount * sizeof(CharacterRange));
264 if (!new_ranges)
265 return OutOfMemory;
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;
272 return Ok;
275 GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat *format, REAL firsttab,
276 INT count, GDIPCONST REAL *tabs)
278 TRACE("(%p, %0.2f, %i, %p)\n", format, firsttab, count, tabs);
280 if(!format || !tabs)
281 return InvalidParameter;
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;
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;
299 format->firsttab = firsttab;
300 format->tabcount = count;
301 memcpy(format->tabs, tabs, sizeof(REAL)*count);
304 return Ok;
307 GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format,
308 StringTrimming trimming)
310 TRACE("(%p, %i)\n", format, trimming);
312 if(!format)
313 return InvalidParameter;
315 format->trimming = trimming;
317 return Ok;
320 GpStatus WINGDIPAPI GdipSetStringFormatFlags(GpStringFormat *format, INT flags)
322 TRACE("(%p, %x)\n", format, flags);
324 if(!format)
325 return InvalidParameter;
327 format->attr = flags;
329 return Ok;
332 GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat)
334 if(!format || !newFormat)
335 return InvalidParameter;
337 *newFormat = GdipAlloc(sizeof(GpStringFormat));
338 if(!*newFormat) return OutOfMemory;
340 **newFormat = *format;
342 if(format->tabcount > 0){
343 (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount);
344 if(!(*newFormat)->tabs){
345 GdipFree(*newFormat);
346 return OutOfMemory;
348 memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount);
350 else
351 (*newFormat)->tabs = NULL;
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;
360 memcpy((*newFormat)->character_ranges, format->character_ranges,
361 sizeof(CharacterRange) * format->range_count);
363 else
364 (*newFormat)->character_ranges = NULL;
366 TRACE("%p %p\n",format,newFormat);
368 return Ok;
371 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
373 GpStatus stat;
375 if(!format)
376 return InvalidParameter;
378 stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox |
379 StringFormatFlagsLineLimit |
380 StringFormatFlagsNoClip, LANG_NEUTRAL, format);
381 if(stat != Ok)
382 return stat;
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;
392 TRACE("%p => %p\n", format, *format);
394 return Ok;