1 /* Fo
2  * fo-property-force-page-count.c: 'force-page-count' property
3  *
4  * Copyright (C) 2001-2006 Sun Microsystems
5  * Copyright (C) 2007-2010 Menteith Consulting Ltd
6  * Copyright (C) 2011 Mentea
7  *
8  * See COPYING for the status of this software.
9  */
10 
11 #include <string.h>
12 #include "fo-utils.h"
13 #include "fo-context.h"
14 #include "datatype/fo-datatype.h"
15 #include "property/fo-property-private.h"
16 #include "property/fo-property-font-size.h"
17 #include "property/fo-property-force-page-count.h"
18 
19 /**
20  * SECTION:fo-property-force-page-count
21  * @short_description: 'force-page-count' property
22  *
23  * Inherited: FALSE
24  *
25  * Shorthand: FALSE
26  *
27  * Value: auto | even | odd | end-on-even | end-on-odd | no-force | inherit
28  *
29  * Initial value: auto
30  *
31  * Definition: <ulink url="http://www.w3.org/TR/xsl11/&num;force-page-count">http://www.w3.org/TR/xsl11/&num;force-page-count</ulink>
32  */
33 
34 struct _FoPropertyForcePageCount
35 {
36   FoProperty parent_instance;
37 };
38 
39 struct _FoPropertyForcePageCountClass
40 {
41   FoPropertyClass parent_class;
42 };
43 
44 static void _init         (FoPropertyForcePageCount      *property_force_page_count);
45 static void _class_init   (FoPropertyForcePageCountClass *klass);
46 
47 static FoDatatype * _resolve_enum (const gchar *token,
48                                    FoContext   *context,
49                                    GError     **error);
50 static FoDatatype * _validate     (FoDatatype  *datatype,
51                                    FoContext   *context,
52                                    GError     **error);
53 
54 static const gchar class_name[] = "force-page-count";
55 static gpointer parent_class;
56 
57 /**
58  * fo_property_force_page_count_get_type:
59  *
60  * Register the #FoPropertyForcePageCount type if not already registered and
61  * return its #GType value.
62  *
63  * Return value: #GType of #FoPropertyForcePageCount.
64  **/
65 GType
fo_property_force_page_count_get_type(void)66 fo_property_force_page_count_get_type (void)
67 {
68   static GType object_type = 0;
69 
70   if (!object_type)
71     {
72       static const GTypeInfo object_info =
73       {
74         sizeof (FoPropertyForcePageCountClass),
75         NULL,           /* base_init */
76         NULL,           /* base_finalize */
77         (GClassInitFunc) _class_init,
78         NULL,           /* class_finalize */
79         NULL,           /* class_data */
80         sizeof (FoPropertyForcePageCount),
81         0,              /* n_preallocs */
82         (GInstanceInitFunc) _init,
83 	NULL		/* value_table */
84       };
85 
86       object_type = g_type_register_static (FO_TYPE_PROPERTY,
87                                             class_name,
88                                             &object_info, 0);
89     }
90 
91   return object_type;
92 }
93 
94 /**
95  * _init:
96  * @force_page_count: #FoPropertyForcePageCount object to initialise.
97  *
98  * Implements #GInstanceInitFunc for #FoPropertyForcePageCount.
99  **/
100 static void
_init(FoPropertyForcePageCount * force_page_count)101 _init (FoPropertyForcePageCount *force_page_count)
102 {
103   FO_PROPERTY (force_page_count)->value =
104     g_object_ref (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_AUTO));
105 }
106 
107 /**
108  * _class_init:
109  * @klass: #FoPropertyForcePageCountClass object to initialise.
110  *
111  * Implements #GClassInitFunc for #FoPropertyForcePageCountClass.
112  **/
113 static void
_class_init(FoPropertyForcePageCountClass * klass)114 _class_init (FoPropertyForcePageCountClass *klass)
115 {
116   GObjectClass *object_class = G_OBJECT_CLASS (klass);
117   FoPropertyClass *property_class = FO_PROPERTY_CLASS (klass);
118 
119   parent_class = g_type_class_peek_parent (klass);
120 
121 
122   property_class->is_inherited = FALSE;
123   property_class->is_shorthand = FALSE;
124   property_class->resolve_enum =
125     _resolve_enum;
126   property_class->validate =
127     _validate;
128   property_class->get_initial =
129     fo_property_force_page_count_get_initial;
130 }
131 
132 
133 /**
134  * fo_property_force_page_count_new:
135  *
136  * Creates a new #FoPropertyForcePageCount initialized to default value.
137  *
138  * Return value: the new #FoPropertyForcePageCount.
139  **/
140 FoProperty*
fo_property_force_page_count_new(void)141 fo_property_force_page_count_new (void)
142 {
143   FoProperty* force_page_count;
144 
145   force_page_count =
146     FO_PROPERTY (g_object_new (fo_property_force_page_count_get_type (),
147                                NULL));
148 
149   return force_page_count;
150 }
151 
152 /**
153  * _resolve_enum:
154  * @token:   Token from the XML attribute value to be evaluated as an
155  *           enumeration token.
156  * @context: #FoContext object from which to possibly inherit values.
157  * @error:   Information about any error that has occurred.
158  *
159  * Compare @token against the enumeration tokens that are valid for the
160  * current FO property.  If @token is valid, returns either an #FoEnum datatype
161  * representing the enumeration token or a different datatype representing
162  * the enumeration token's resolved value.  If @token is not valid,
163  * sets @error and returns NULL.
164  *
165  * Return value: Resolved enumeration value or NULL.
166  **/
167 static FoDatatype *
_resolve_enum(const gchar * token,FoContext * context,GError ** error)168 _resolve_enum (const gchar *token,
169                FoContext   *context,
170                GError     **error)
171 {
172   g_return_val_if_fail (token != NULL, NULL);
173   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
174   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
175 
176   if ((strcmp (token, "auto") == 0) ||
177       (strcmp (token, "even") == 0) ||
178       (strcmp (token, "odd") == 0) ||
179       (strcmp (token, "end-on-even") == 0) ||
180       (strcmp (token, "end-on-odd") == 0) ||
181       (strcmp (token, "no-force") == 0))
182     {
183       return g_object_ref (fo_enum_factory_get_enum_by_nick (token));
184     }
185   else
186     {
187       g_set_error (error,
188 		   FO_FO_ERROR,
189 		   FO_FO_ERROR_ENUMERATION_TOKEN,
190 		   _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
191 		   class_name,
192 		   token);
193       return NULL;
194     }
195 }
196 
197 /**
198  * _validate:
199  * @datatype: #FoDatatype to be validated against allowed datatypes and
200  *            values for current property.
201  * @context:  #FoContext object from which to possibly inherit values.
202  * @error:    Information about any error that has occurred.
203  *
204  * Validates @datatype against allowed values.  Returns @datatype, a
205  * replacement datatype value, or NULL if validation failed.
206  *
207  * Return value: Valid datatype value or NULL.
208  **/
209 FoDatatype*
_validate(FoDatatype * datatype,FoContext * context,GError ** error)210 _validate (FoDatatype *datatype,
211            FoContext  *context,
212            GError    **error)
213 {
214   FoDatatype *new_datatype;
215   GError     *tmp_error = NULL;
216   gchar      *token;
217 
218   g_return_val_if_fail (datatype != NULL, NULL);
219   g_return_val_if_fail (FO_IS_DATATYPE (datatype), NULL);
220   g_return_val_if_fail (context != NULL, NULL);
221   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
222   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
223 
224   if (FO_IS_ENUM (datatype))
225     {
226       FoEnumEnum value = fo_enum_get_value (datatype);
227 
228       if ((value == FO_ENUM_ENUM_AUTO) ||
229           (value == FO_ENUM_ENUM_EVEN) ||
230           (value == FO_ENUM_ENUM_ODD) ||
231           (value == FO_ENUM_ENUM_END_ON_EVEN) ||
232           (value == FO_ENUM_ENUM_END_ON_ODD) ||
233           (value == FO_ENUM_ENUM_NO_FORCE))
234 	{
235 	  return datatype;
236 	}
237       else
238 	{
239 	  gchar *datatype_sprintf = fo_object_sprintf (datatype);
240 
241 	  g_set_error (error,
242 		       FO_FO_ERROR,
243 		       FO_FO_ERROR_ENUMERATION_TOKEN,
244 		       _(fo_fo_error_messages[FO_FO_ERROR_ENUMERATION_TOKEN]),
245 		       class_name,
246 		       datatype_sprintf,
247 		       g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
248 
249 	  g_object_unref (datatype);
250 
251 	  g_free (datatype_sprintf);
252 
253 	  return NULL;
254 	}
255     }
256   else if (FO_IS_STRING (datatype))
257     {
258       token = fo_string_get_value (datatype);
259 
260       new_datatype =
261         _resolve_enum (token, context, &tmp_error);
262 
263       g_object_unref (datatype);
264 
265       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
266 
267       return new_datatype;
268     }
269   else if (FO_IS_NAME (datatype))
270     {
271       token = fo_name_get_value (datatype);
272 
273       new_datatype =
274         _resolve_enum (token, context, &tmp_error);
275 
276       g_object_unref (datatype);
277 
278       fo_propagate_and_return_val_if_error (error, tmp_error, NULL);
279 
280       return new_datatype;
281     }
282   else
283     {
284       gchar *datatype_sprintf = fo_object_sprintf (datatype);
285 
286       g_set_error (error,
287 		   FO_FO_ERROR,
288 		   FO_FO_ERROR_DATATYPE,
289 		   _(fo_fo_error_messages[FO_FO_ERROR_DATATYPE]),
290 		   class_name,
291 		   datatype_sprintf,
292 		   g_type_name (G_TYPE_FROM_INSTANCE (datatype)));
293 
294       g_object_unref (datatype);
295 
296       g_free (datatype_sprintf);
297 
298       return NULL;
299     }
300 }
301 
302 /**
303  * fo_property_force_page_count_get_initial:
304  *
305  * Get an instance of the property with the correct initial value.
306  *
307  * Return value: An instance of the property.
308  **/
309 FoProperty*
fo_property_force_page_count_get_initial(void)310 fo_property_force_page_count_get_initial (void)
311 {
312   static FoProperty *force_page_count = NULL;
313 
314   if (force_page_count == NULL)
315     {
316       force_page_count =
317 	fo_property_force_page_count_new ();
318     }
319 
320   return force_page_count;
321 }
322