- Sync gdiplus with Wine head
[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 <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(GDIPCONST GpStringFormat *format, INT flags)
288 {
289 FIXME("format (%p) flags (%d)\n", format, flags);
290
291 return Ok;
292 }
293
294 GpStatus WINGDIPAPI GdipCloneStringFormat(GDIPCONST GpStringFormat *format, GpStringFormat **newFormat)
295 {
296 if(!format || !newFormat)
297 return InvalidParameter;
298
299 *newFormat = GdipAlloc(sizeof(GpStringFormat));
300 if(!*newFormat) return OutOfMemory;
301
302 **newFormat = *format;
303
304 if(format->tabcount > 0){
305 (*newFormat)->tabs = GdipAlloc(sizeof(REAL) * format->tabcount);
306 if(!(*newFormat)->tabs){
307 GdipFree(*newFormat);
308 return OutOfMemory;
309 }
310 memcpy((*newFormat)->tabs, format->tabs, sizeof(REAL) * format->tabcount);
311 }
312 else
313 (*newFormat)->tabs = NULL;
314
315 TRACE("%p %p\n",format,newFormat);
316
317 return Ok;
318 }
319
320 GpStatus WINGDIPAPI GdipStringFormatGetGenericTypographic(GpStringFormat **format)
321 {
322 GpStatus stat;
323
324 if(!format)
325 return InvalidParameter;
326
327 stat = GdipCreateStringFormat(StringFormatFlagsNoFitBlackBox |
328 StringFormatFlagsLineLimit |
329 StringFormatFlagsNoClip, LANG_NEUTRAL, format);
330 if(stat != Ok)
331 return stat;
332
333 (*format)->digitlang = LANG_NEUTRAL;
334 (*format)->digitsub = StringDigitSubstituteUser;
335 (*format)->trimming = StringTrimmingNone;
336 (*format)->hkprefix = HotkeyPrefixNone;
337 (*format)->align = StringAlignmentNear;
338 (*format)->vertalign = StringAlignmentNear;
339
340 return Ok;
341 }