api-ms-win-core-comm-l1-1-0: Add dll.
[wine.git] / dlls / gdiplus / stringformat.c
blobe376e7b36c3dee7d68f4150a1515874545a50571
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 const GpStringFormat default_drawstring_format =
38 LANG_NEUTRAL,
39 LANG_NEUTRAL,
40 StringAlignmentNear,
41 StringTrimmingCharacter,
42 HotkeyPrefixNone,
43 StringAlignmentNear,
44 StringDigitSubstituteUser,
46 0.0,
47 NULL,
48 NULL,
50 FALSE
53 static GpStringFormat generic_default_format;
54 static GpStringFormat generic_typographic_format;
56 void init_generic_string_formats(void)
58 memcpy(&generic_default_format, &default_drawstring_format, sizeof(generic_default_format));
60 memcpy(&generic_typographic_format, &default_drawstring_format, sizeof(generic_typographic_format));
61 generic_typographic_format.attr = StringFormatFlagsNoFitBlackBox | StringFormatFlagsLineLimit |
62 StringFormatFlagsNoClip;
63 generic_typographic_format.trimming = StringTrimmingNone;
64 generic_typographic_format.generic_typographic = TRUE;
67 void free_generic_string_formats(void)
69 heap_free(generic_default_format.character_ranges);
70 heap_free(generic_default_format.tabs);
72 heap_free(generic_typographic_format.character_ranges);
73 heap_free(generic_typographic_format.tabs);
76 GpStatus WINGDIPAPI GdipCreateStringFormat(INT attr, LANGID lang,
77 GpStringFormat **format)
79 TRACE("(%i, %x, %p)\n", attr, lang, format);
81 if(!format)
82 return InvalidParameter;
84 *format = heap_alloc_zero(sizeof(GpStringFormat));
85 if(!*format) return OutOfMemory;
87 (*format)->attr = attr;
88 (*format)->lang = lang;
89 (*format)->digitlang = LANG_NEUTRAL;
90 (*format)->trimming = StringTrimmingCharacter;
91 (*format)->digitsub = StringDigitSubstituteUser;
92 (*format)->character_ranges = NULL;
93 (*format)->range_count = 0;
94 (*format)->generic_typographic = FALSE;
95 /* tabstops */
96 (*format)->tabcount = 0;
97 (*format)->firsttab = 0.0;
98 (*format)->tabs = NULL;
100 TRACE("<-- %p\n", *format);
102 return Ok;
105 GpStatus WINGDIPAPI GdipDeleteStringFormat(GpStringFormat *format)
107 if(!format)
108 return InvalidParameter;
110 if (format == &generic_default_format || format == &generic_typographic_format)
111 return Ok;
113 heap_free(format->character_ranges);
114 heap_free(format->tabs);
115 heap_free(format);
117 return Ok;
120 GpStatus WINGDIPAPI GdipStringFormatGetGenericDefault(GpStringFormat **format)
122 if (!format)
123 return InvalidParameter;
125 *format = &generic_default_format;
127 return Ok;
130 GpStatus WINGDIPAPI GdipGetStringFormatAlign(GpStringFormat *format,
131 StringAlignment *align)
133 if(!format || !align)
134 return InvalidParameter;
136 *align = format->align;
138 return Ok;
141 GpStatus WINGDIPAPI GdipGetStringFormatDigitSubstitution(GDIPCONST GpStringFormat *format,
142 LANGID *language, StringDigitSubstitute *substitute)
144 if(!format)
145 return InvalidParameter;
147 if(language) *language = format->digitlang;
148 if(substitute) *substitute = format->digitsub;
150 return Ok;
153 GpStatus WINGDIPAPI GdipGetStringFormatFlags(GDIPCONST GpStringFormat* format,
154 INT* flags)
156 if (!(format && flags))
157 return InvalidParameter;
159 *flags = format->attr;
161 return Ok;
164 GpStatus WINGDIPAPI GdipGetStringFormatHotkeyPrefix(GDIPCONST GpStringFormat
165 *format, INT *hkpx)
167 if(!format || !hkpx)
168 return InvalidParameter;
170 *hkpx = (INT)format->hkprefix;
172 return Ok;
175 GpStatus WINGDIPAPI GdipGetStringFormatLineAlign(GpStringFormat *format,
176 StringAlignment *align)
178 if(!format || !align)
179 return InvalidParameter;
181 *align = format->line_align;
183 return Ok;
186 GpStatus WINGDIPAPI GdipGetStringFormatMeasurableCharacterRangeCount(
187 GDIPCONST GpStringFormat *format, INT *count)
189 if (!(format && count))
190 return InvalidParameter;
192 TRACE("%p %p\n", format, count);
194 *count = format->range_count;
196 return Ok;
199 GpStatus WINGDIPAPI GdipGetStringFormatTabStopCount(GDIPCONST GpStringFormat *format,
200 INT *count)
202 if(!format || !count)
203 return InvalidParameter;
205 *count = format->tabcount;
207 return Ok;
210 GpStatus WINGDIPAPI GdipGetStringFormatTabStops(GDIPCONST GpStringFormat *format, INT count,
211 REAL *firsttab, REAL *tabs)
213 if(!format || !firsttab || !tabs)
214 return InvalidParameter;
216 /* native simply crashes on count < 0 */
217 if(count != 0)
218 memcpy(tabs, format->tabs, sizeof(REAL)*count);
220 *firsttab = format->firsttab;
222 return Ok;
225 GpStatus WINGDIPAPI GdipGetStringFormatTrimming(GpStringFormat *format,
226 StringTrimming *trimming)
228 if(!format || !trimming)
229 return InvalidParameter;
231 *trimming = format->trimming;
233 return Ok;
236 GpStatus WINGDIPAPI GdipSetStringFormatAlign(GpStringFormat *format,
237 StringAlignment align)
239 TRACE("(%p, %i)\n", format, align);
241 if(!format)
242 return InvalidParameter;
244 format->align = align;
246 return Ok;
249 /*FIXME: digit substitution actually not implemented, get/set only */
250 GpStatus WINGDIPAPI GdipSetStringFormatDigitSubstitution(GpStringFormat *format,
251 LANGID language, StringDigitSubstitute substitute)
253 TRACE("(%p, %x, %i)\n", format, language, substitute);
255 if(!format)
256 return InvalidParameter;
258 format->digitlang = language;
259 format->digitsub = substitute;
261 return Ok;
264 GpStatus WINGDIPAPI GdipSetStringFormatHotkeyPrefix(GpStringFormat *format,
265 INT hkpx)
267 TRACE("(%p, %i)\n", format, hkpx);
269 if(!format || hkpx < 0 || hkpx > 2)
270 return InvalidParameter;
272 format->hkprefix = (HotkeyPrefix) hkpx;
274 return Ok;
277 GpStatus WINGDIPAPI GdipSetStringFormatLineAlign(GpStringFormat *format,
278 StringAlignment align)
280 TRACE("(%p, %i)\n", format, align);
282 if(!format)
283 return InvalidParameter;
285 format->line_align = align;
287 return Ok;
290 GpStatus WINGDIPAPI GdipSetStringFormatMeasurableCharacterRanges(
291 GpStringFormat *format, INT rangeCount, GDIPCONST CharacterRange *ranges)
293 CharacterRange *new_ranges;
295 if (!(format && ranges))
296 return InvalidParameter;
298 TRACE("%p, %d, %p\n", format, rangeCount, ranges);
300 new_ranges = heap_alloc_zero(rangeCount * sizeof(CharacterRange));
301 if (!new_ranges)
302 return OutOfMemory;
304 heap_free(format->character_ranges);
305 format->character_ranges = new_ranges;
306 memcpy(format->character_ranges, ranges, sizeof(CharacterRange) * rangeCount);
307 format->range_count = rangeCount;
309 return Ok;
312 GpStatus WINGDIPAPI GdipSetStringFormatTabStops(GpStringFormat *format, REAL firsttab,
313 INT count, GDIPCONST REAL *tabs)
315 TRACE("(%p, %0.2f, %i, %p)\n", format, firsttab, count, tabs);
317 if(!format || !tabs)
318 return InvalidParameter;
320 if(count > 0){
321 if(firsttab < 0.0) return NotImplemented;
322 /* first time allocation */
323 if(format->tabcount == 0){
324 format->tabs = heap_alloc_zero(sizeof(REAL)*count);
325 if(!format->tabs)
326 return OutOfMemory;
328 /* reallocation */
329 if((format->tabcount < count) && (format->tabcount > 0)){
330 REAL *ptr;
331 ptr = heap_realloc(format->tabs, sizeof(REAL)*count);
332 if(!ptr)
333 return OutOfMemory;
334 format->tabs = ptr;
336 format->firsttab = firsttab;
337 format->tabcount = count;
338 memcpy(format->tabs, tabs, sizeof(REAL)*count);
341 return Ok;
344 GpStatus WINGDIPAPI GdipSetStringFormatTrimming(GpStringFormat *format,
345 StringTrimming trimming)
347 TRACE("(%p, %i)\n", format, trimming);
349 if(!format)
350 return InvalidParameter;
352 format->trimming = trimming;
354 return Ok;
357 GpStatus WINGDIPAPI GdipSetStringFormatFlags(GpStringFormat *format, INT flags)
359 TRACE("(%p, %x)\n", format, flags);
361 if(!format)
362 return InvalidParameter;
364 format->attr = flags;
366 return Ok;
369 GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat)
371 if(!format || !newFormat)
372 return InvalidParameter;
374 *newFormat = heap_alloc_zero(sizeof(GpStringFormat));
375 if(!*newFormat) return OutOfMemory;
377 **newFormat = *format;
379 if(format->tabcount > 0){
380 (*newFormat)->tabs = heap_alloc_zero(sizeof(REAL) * format->tabcount);
381 if(!(*newFormat)->tabs){
382 heap_free(*newFormat);
383 return OutOfMemory;
385 memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount);
387 else
388 (*newFormat)->tabs = NULL;
390 if(format->range_count > 0){
391 (*newFormat)->character_ranges = heap_alloc_zero(sizeof(CharacterRange) * format->range_count);
392 if(!(*newFormat)->character_ranges){
393 heap_free((*newFormat)->tabs);
394 heap_free(*newFormat);
395 return OutOfMemory;
397 memcpy((*newFormat)->character_ranges, format->character_ranges,
398 sizeof(CharacterRange) * format->range_count);
400 else
401 (*newFormat)->character_ranges = NULL;
403 TRACE("%p %p\n",format,newFormat);
405 return Ok;
408 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
410 if(!format)
411 return InvalidParameter;
413 *format = &generic_typographic_format;
415 TRACE("%p => %p\n", format, *format);
417 return Ok;