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