1 /* Fo
2 * fo-property-keep-with-previous.c: 'keep-with-previous' property
3 *
4 * Copyright (C) 2001 Sun Microsystems
5 * Copyright (C) 2007 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include <string.h>
11 #include "fo-utils.h"
12 #include "fo-context.h"
13 #include "datatype/fo-datatype.h"
14 #include "property/fo-property-private.h"
15 #include "property/fo-property-font-size.h"
16 #include "property/fo-property-keep-with-previous.h"
17
18 struct _FoPropertyKeepWithPrevious
19 {
20 FoProperty parent_instance;
21 };
22
23 struct _FoPropertyKeepWithPreviousClass
24 {
25 FoPropertyClass parent_class;
26 };
27
28 static void fo_property_keep_with_previous_init (FoPropertyKeepWithPrevious *property_keep_with_previous);
29 static void fo_property_keep_with_previous_base_init (FoPropertyKeepWithPreviousClass *klass);
30 static void fo_property_keep_with_previous_base_finalize (FoPropertyKeepWithPreviousClass *klass);
31 static void fo_property_keep_with_previous_class_init (FoPropertyKeepWithPreviousClass *klass);
32 static void fo_property_keep_with_previous_finalize (GObject *object);
33
34 static FoDatatype* fo_property_keep_with_previous_resolve_enum (const gchar *token,
35 FoContext *context,
36 GError **error);
37 static FoDatatype* fo_property_keep_with_previous_validate (FoDatatype *datatype,
38 FoContext *context,
39 GError **error);
40
41 static const gchar class_name[] = "keep-with-previous";
42 static gpointer parent_class;
43 static FoDatatype *enum_auto;
44 static FoDatatype *enum_always;
45
46 /**
47 * fo_property_keep_with_previous_get_type:
48 *
49 * Register the #FoPropertyKeepWithPrevious type if not already registered and
50 * return its #GType value.
51 *
52 * Return value: #GType of #FoPropertyKeepWithPrevious.
53 **/
54 GType
fo_property_keep_with_previous_get_type(void)55 fo_property_keep_with_previous_get_type (void)
56 {
57 static GType object_type = 0;
58
59 if (!object_type)
60 {
61 static const GTypeInfo object_info =
62 {
63 sizeof (FoPropertyKeepWithPreviousClass),
64 (GBaseInitFunc) fo_property_keep_with_previous_base_init,
65 (GBaseFinalizeFunc) fo_property_keep_with_previous_base_finalize,
66 (GClassInitFunc) fo_property_keep_with_previous_class_init,
67 NULL, /* class_finalize */
68 NULL, /* class_data */
69 sizeof (FoPropertyKeepWithPrevious),
70 0, /* n_preallocs */
71 (GInstanceInitFunc) fo_property_keep_with_previous_init,
72 NULL /* value_table */
73 };
74
75 object_type = g_type_register_static (FO_TYPE_PROPERTY,
76 class_name,
77 &object_info, 0);
78 }
79
80 return object_type;
81 }
82
83 /**
84 * fo_property_keep_with_previous_init:
85 * @keep_with_previous: #FoPropertyKeepWithPrevious object to initialise.
86 *
87 * Implements #GInstanceInitFunc for #FoPropertyKeepWithPrevious.
88 **/
89 void
fo_property_keep_with_previous_init(FoPropertyKeepWithPrevious * keep_with_previous)90 fo_property_keep_with_previous_init (FoPropertyKeepWithPrevious *keep_with_previous)
91 {
92 FO_PROPERTY (keep_with_previous)->value =
93 g_object_ref (fo_keep_get_keep_auto ());
94 }
95
96 /**
97 * fo_property_keep_with_previous_base_init:
98 * @klass: #FoPropertyKeepWithPreviousClass object to initialise.
99 *
100 * Implements #GBaseInitFunc for #FoPropertyKeepWithPreviousClass.
101 **/
102 void
fo_property_keep_with_previous_base_init(FoPropertyKeepWithPreviousClass * klass G_GNUC_UNUSED)103 fo_property_keep_with_previous_base_init (FoPropertyKeepWithPreviousClass *klass G_GNUC_UNUSED)
104 {
105 enum_auto =
106 g_object_new (FO_TYPE_ENUM,
107 "enum-class",
108 g_type_class_ref (FO_TYPE_ENUM_ENUM),
109 "value",
110 FO_ENUM_ENUM_AUTO,
111 NULL);
112 enum_always =
113 g_object_new (FO_TYPE_ENUM,
114 "enum-class",
115 g_type_class_ref (FO_TYPE_ENUM_ENUM),
116 "value",
117 FO_ENUM_ENUM_ALWAYS,
118 NULL);
119 }
120
121 /**
122 * fo_property_keep_with_previous_base_finalize:
123 * @klass: #FoPropertyKeepWithPreviousClass object to finalise.
124 *
125 * Implements #GBaseFinalizeFunc for #FoPropertyKeepWithPreviousClass.
126 **/
127 void
fo_property_keep_with_previous_base_finalize(FoPropertyKeepWithPreviousClass * klass G_GNUC_UNUSED)128 fo_property_keep_with_previous_base_finalize (FoPropertyKeepWithPreviousClass *klass G_GNUC_UNUSED)
129 {
130 g_object_unref (enum_auto);
131 g_object_unref (enum_always);
132 }
133
134 /**
135 * fo_property_keep_with_previous_class_init:
136 * @klass: #FoPropertyKeepWithPreviousClass object to initialise.
137 *
138 * Implements #GClassInitFunc for #FoPropertyKeepWithPreviousClass.
139 **/
140 void
fo_property_keep_with_previous_class_init(FoPropertyKeepWithPreviousClass * klass)141 fo_property_keep_with_previous_class_init (FoPropertyKeepWithPreviousClass *klass)
142 {
143 GObjectClass *object_class = G_OBJECT_CLASS (klass);
144 FoPropertyClass *property_class = FO_PROPERTY_CLASS (klass);
145
146 parent_class = g_type_class_peek_parent (klass);
147
148 object_class->finalize = fo_property_keep_with_previous_finalize;
149
150 property_class->is_inherited = FALSE;
151 property_class->is_shorthand = FALSE;
152 property_class->resolve_enum =
153 fo_property_keep_with_previous_resolve_enum;
154 property_class->validate =
155 fo_property_keep_with_previous_validate;
156 property_class->get_initial =
157 fo_property_keep_with_previous_get_initial;
158 }
159
160 /**
161 * fo_property_keep_with_previous_finalize:
162 * @object: #FoPropertyKeepWithPrevious object to finalize.
163 *
164 * Implements #GObjectFinalizeFunc for #FoPropertyKeepWithPrevious.
165 **/
166 void
fo_property_keep_with_previous_finalize(GObject * object)167 fo_property_keep_with_previous_finalize (GObject *object)
168 {
169 FoPropertyKeepWithPrevious *keep_with_previous;
170
171 keep_with_previous = FO_PROPERTY_KEEP_WITH_PREVIOUS (object);
172
173 G_OBJECT_CLASS (parent_class)->finalize (object);
174 }
175
176
177 /**
178 * fo_property_keep_with_previous_new:
179 *
180 * Creates a new #FoPropertyKeepWithPrevious initialized to default value.
181 *
182 * Return value: the new #FoPropertyKeepWithPrevious.
183 **/
184 FoProperty*
fo_property_keep_with_previous_new(void)185 fo_property_keep_with_previous_new (void)
186 {
187 FoProperty* keep_with_previous;
188
189 keep_with_previous =
190 FO_PROPERTY (g_object_new (fo_property_keep_with_previous_get_type (),
191 NULL));
192
193 return keep_with_previous;
194 }
195
196 /**
197 * fo_property_keep_with_previous_resolve_enum:
198 * @token: Token from the XML attribute value to be evaluated as an
199 * enumeration token.
200 * @context: #FoContext object from which to possibly inherit values.
201 * @error: Information about any error that has occurred.
202 *
203 * Compare @token against the enumeration tokens that are valid for the
204 * current FO property. If @token is valid, returns either an #FoEnum datatype
205 * representing the enumeration token or a different datatype representing
206 * the enumeration token's resolved value. If @token is not valid,
207 * sets @error and returns NULL.
208 *
209 * Return value: Resolved enumeration value or NULL.
210 **/
211 FoDatatype*
fo_property_keep_with_previous_resolve_enum(const gchar * token,FoContext * context,GError ** error)212 fo_property_keep_with_previous_resolve_enum (const gchar *token,
213 FoContext *context,
214 GError **error)
215 {
216 g_return_val_if_fail (token != NULL, NULL);
217 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
218 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
219
220 if (strcmp (token, "auto") == 0)
221 {
222 return g_object_ref (fo_keep_get_keep_auto ());
223 }
224 else if (strcmp (token, "always") == 0)
225 {
226 return g_object_ref (fo_keep_get_keep_always ());
227 }
228 else if (strcmp (token, "inherit") == 0)
229 {
230 return g_object_ref (fo_context_get_keep_with_previous (context));
231 }
232 else
233 {
234 g_set_error (error,
235 FO_FO_ERROR,
236 FO_FO_ERROR_ENUMERATION_TOKEN,
237 _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
238 class_name,
239 token);
240 return NULL;
241 }
242 }
243
244 /**
245 * fo_property_keep_with_previous_validate:
246 * @datatype: #FoDatatype to be validated against allowed datatypes and
247 * values for current property.
248 * @context: #FoContext object from which to possibly inherit values.
249 * @error: Information about any error that has occurred.
250 *
251 * Validates @datatype against allowed values. Returns @datatype, a
252 * replacement datatype value, or NULL if validation failed.
253 *
254 * Return value: Valid datatype value or NULL.
255 **/
256 FoDatatype*
fo_property_keep_with_previous_validate(FoDatatype * datatype,FoContext * context,GError ** error)257 fo_property_keep_with_previous_validate (FoDatatype *datatype,
258 FoContext *context,
259 GError **error)
260 {
261 FoDatatype *new_datatype;
262 GError *tmp_error = NULL;
263 gchar *token;
264
265 g_return_val_if_fail (datatype != NULL, NULL);
266 g_return_val_if_fail (FO_IS_DATATYPE (datatype), NULL);
267 g_return_val_if_fail (context != NULL, NULL);
268 g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
269 g_return_val_if_fail (error == NULL || *error == NULL, NULL);
270
271 if (FO_IS_KEEP (datatype))
272 {
273 return datatype;
274 }
275 else if (FO_IS_ENUM (datatype))
276 {
277 if ((fo_enum_get_value (datatype) == FO_ENUM_ENUM_AUTO) ||
278 (fo_enum_get_value (datatype) == FO_ENUM_ENUM_ALWAYS))
279 {
280 new_datatype = fo_keep_new_with_value (datatype);
281
282 g_object_unref (datatype);
283
284 return new_datatype;
285 }
286 else
287 {
288 gchar *datatype_sprintf = fo_object_sprintf (datatype);
289
290 g_set_error (error,
291 FO_FO_ERROR,
292 FO_FO_ERROR_DATATYPE,
293 _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
294 class_name,
295 datatype_sprintf,
296 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
297
298 g_object_unref (datatype);
299
300 g_free (datatype_sprintf);
301
302 return NULL;
303 }
304 }
305 else if (FO_IS_STRING (datatype))
306 {
307 token = fo_string_get_value (datatype);
308
309 new_datatype =
310 fo_property_keep_with_previous_resolve_enum (token, context, &tmp_error);
311
312 g_object_unref (datatype);
313
314 if (tmp_error != NULL)
315 {
316 g_propagate_error (error, tmp_error);
317 return NULL;
318 }
319
320 return new_datatype;
321 }
322 else if (FO_IS_NAME (datatype))
323 {
324 token = fo_name_get_value (datatype);
325
326 new_datatype =
327 fo_property_keep_with_previous_resolve_enum (token, context, &tmp_error);
328
329 g_object_unref (datatype);
330
331 if (tmp_error != NULL)
332 {
333 g_propagate_error (error, tmp_error);
334 return NULL;
335 }
336
337 return new_datatype;
338 }
339 else if (FO_IS_INTEGER (datatype))
340 {
341 new_datatype = fo_keep_new_with_value (datatype);
342
343 g_object_unref (datatype);
344
345 return new_datatype;
346 }
347 else if (FO_IS_NUMBER (datatype))
348 {
349 FoDatatype *integer_datatype =
350 fo_integer_new_with_value (fo_number_get_value (datatype));
351
352 g_object_unref (datatype);
353
354 new_datatype = fo_keep_new_with_value (integer_datatype);
355
356 g_object_unref (integer_datatype);
357
358 return new_datatype;
359 }
360 else
361 {
362 gchar *datatype_sprintf = fo_object_sprintf (datatype);
363
364 g_set_error (error,
365 FO_FO_ERROR,
366 FO_FO_ERROR_DATATYPE,
367 _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
368 class_name,
369 datatype_sprintf,
370 g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
371
372 g_object_unref (datatype);
373
374 g_free (datatype_sprintf);
375
376 return NULL;
377 }
378 }
379
380 /**
381 * fo_property_keep_with_previous_get_initial:
382 *
383 * Get an instance of the property with the correct initial value.
384 *
385 * Return value: An instance of the property.
386 **/
387 FoProperty*
fo_property_keep_with_previous_get_initial(void)388 fo_property_keep_with_previous_get_initial (void)
389 {
390 static FoProperty *keep_with_previous = NULL;
391
392 if (keep_with_previous == NULL)
393 {
394 keep_with_previous = fo_property_keep_with_previous_new ();
395 }
396
397 return keep_with_previous;
398 }
399