1 /* Fo
2  * fo-property-keep-with-next.c: 'keep-with-next' 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-next.h"
17 
18 struct _FoPropertyKeepWithNext
19 {
20   FoProperty parent_instance;
21 };
22 
23 struct _FoPropertyKeepWithNextClass
24 {
25   FoPropertyClass parent_class;
26 };
27 
28 static void fo_property_keep_with_next_init         (FoPropertyKeepWithNext      *property_keep_with_next);
29 static void fo_property_keep_with_next_base_init   (FoPropertyKeepWithNextClass *klass);
30 static void fo_property_keep_with_next_base_finalize   (FoPropertyKeepWithNextClass *klass);
31 static void fo_property_keep_with_next_class_init   (FoPropertyKeepWithNextClass *klass);
32 static void fo_property_keep_with_next_finalize     (GObject       *object);
33 
34 static FoDatatype* fo_property_keep_with_next_resolve_enum (const gchar *token,
35                                                             FoContext   *context,
36                                                             GError     **error);
37 static FoDatatype* fo_property_keep_with_next_validate (FoDatatype *datatype,
38                                                         FoContext  *context,
39                                                         GError    **error);
40 
41 static const gchar class_name[] = "keep-with-next";
42 static gpointer parent_class;
43 static FoDatatype *enum_auto;
44 static FoDatatype *enum_always;
45 
46 /**
47  * fo_property_keep_with_next_get_type:
48  *
49  * Register the #FoPropertyKeepWithNext type if not already registered and
50  * return its #GType value.
51  *
52  * Return value: #GType of #FoPropertyKeepWithNext.
53  **/
54 GType
fo_property_keep_with_next_get_type(void)55 fo_property_keep_with_next_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 (FoPropertyKeepWithNextClass),
64         (GBaseInitFunc) fo_property_keep_with_next_base_init,
65         (GBaseFinalizeFunc) fo_property_keep_with_next_base_finalize,
66         (GClassInitFunc) fo_property_keep_with_next_class_init,
67         NULL,           /* class_finalize */
68         NULL,           /* class_data */
69         sizeof (FoPropertyKeepWithNext),
70         0,              /* n_preallocs */
71         (GInstanceInitFunc) fo_property_keep_with_next_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_next_init:
85  * @keep_with_next: #FoPropertyKeepWithNext object to initialise.
86  *
87  * Implements #GInstanceInitFunc for #FoPropertyKeepWithNext.
88  **/
89 void
fo_property_keep_with_next_init(FoPropertyKeepWithNext * keep_with_next)90 fo_property_keep_with_next_init (FoPropertyKeepWithNext *keep_with_next)
91 {
92   FO_PROPERTY (keep_with_next)->value =
93     g_object_ref (fo_keep_get_keep_auto ());
94 }
95 
96 /**
97  * fo_property_keep_with_next_base_init:
98  * @klass: #FoPropertyKeepWithNextClass object to initialise.
99  *
100  * Implements #GBaseInitFunc for #FoPropertyKeepWithNextClass.
101  **/
102 void
fo_property_keep_with_next_base_init(FoPropertyKeepWithNextClass * klass G_GNUC_UNUSED)103 fo_property_keep_with_next_base_init (FoPropertyKeepWithNextClass *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_next_base_finalize:
123  * @klass: #FoPropertyKeepWithNextClass object to finalise.
124  *
125  * Implements #GBaseFinalizeFunc for #FoPropertyKeepWithNextClass.
126  **/
127 void
fo_property_keep_with_next_base_finalize(FoPropertyKeepWithNextClass * klass G_GNUC_UNUSED)128 fo_property_keep_with_next_base_finalize (FoPropertyKeepWithNextClass *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_next_class_init:
136  * @klass: #FoPropertyKeepWithNextClass object to initialise.
137  *
138  * Implements #GClassInitFunc for #FoPropertyKeepWithNextClass.
139  **/
140 void
fo_property_keep_with_next_class_init(FoPropertyKeepWithNextClass * klass)141 fo_property_keep_with_next_class_init (FoPropertyKeepWithNextClass *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_next_finalize;
149 
150   property_class->is_inherited = FALSE;
151   property_class->is_shorthand = FALSE;
152   property_class->resolve_enum =
153     fo_property_keep_with_next_resolve_enum;
154   property_class->validate =
155     fo_property_keep_with_next_validate;
156   property_class->get_initial =
157     fo_property_keep_with_next_get_initial;
158 }
159 
160 /**
161  * fo_property_keep_with_next_finalize:
162  * @object: #FoPropertyKeepWithNext object to finalize.
163  *
164  * Implements #GObjectFinalizeFunc for #FoPropertyKeepWithNext.
165  **/
166 void
fo_property_keep_with_next_finalize(GObject * object)167 fo_property_keep_with_next_finalize (GObject *object)
168 {
169   FoPropertyKeepWithNext *keep_with_next;
170 
171   keep_with_next = FO_PROPERTY_KEEP_WITH_NEXT (object);
172 
173   G_OBJECT_CLASS (parent_class)->finalize (object);
174 }
175 
176 
177 /**
178  * fo_property_keep_with_next_new:
179  *
180  * Creates a new #FoPropertyKeepWithNext initialized to default value.
181  *
182  * Return value: the new #FoPropertyKeepWithNext.
183  **/
184 FoProperty*
fo_property_keep_with_next_new(void)185 fo_property_keep_with_next_new (void)
186 {
187   FoProperty* keep_with_next;
188 
189   keep_with_next =
190     FO_PROPERTY (g_object_new (fo_property_keep_with_next_get_type (),
191                                NULL));
192 
193   return keep_with_next;
194 }
195 
196 /**
197  * fo_property_keep_with_next_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_next_resolve_enum(const gchar * token,FoContext * context,GError ** error)212 fo_property_keep_with_next_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_next (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_next_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_next_validate(FoDatatype * datatype,FoContext * context,GError ** error)257 fo_property_keep_with_next_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_next_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_next_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_next_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_next_get_initial(void)388 fo_property_keep_with_next_get_initial (void)
389 {
390   static FoProperty *keep_with_next = NULL;
391 
392   if (keep_with_next == NULL)
393     {
394       keep_with_next = fo_property_keep_with_next_new ();
395     }
396 
397   return keep_with_next;
398 }
399