1 /* Fo
2  * fo-property.h: FoProperty superclass of all property classes
3  *
4  * Copyright (C) 2001 Sun Microsystems
5  * Copyright (C) 2007-2008 Menteith Consulting Ltd
6  *
7  * See COPYING for the status of this software.
8  */
9 
10 #include "fo-utils.h"
11 #include "fo-object.h"
12 #include "datatype/fo-all-datatype.h"
13 #include "fo-context.h"
14 #include "fo-property-private.h"
15 #include "fo-property-font-size.h"
16 /*#include <expression-parser.h>*/
17 
18 /**
19  * SECTION:fo-property
20  * @short_description: Abstract FO property type
21  *
22  * Every property is a subtype of #FoProperty.
23  */
24 
25 const gchar *fo_property_error_messages [] = {
26   N_("Property error."),
27   N_("Property expression evaluation failed."),
28   N_("Attempt to convert to enumeration value when property has no values defined."),
29   N_("Values of '%s' property cannot be negative: %s"),
30   N_("Value of property '%s' should not be zero-length.")
31 };
32 
33 enum {
34   PROP_0,
35   PROP_VALUE,
36   PROP_IS_INHERITED,
37   PROP_IS_SHORTHAND
38 };
39 
40 static void fo_property_base_init  (FoPropertyClass *klass);
41 static void fo_property_base_finalize  (FoPropertyClass *klass);
42 static void fo_property_class_init  (FoPropertyClass *klass);
43 static void fo_property_set_property (GObject       *object,
44 				    guint          prop_id,
45 				    const GValue  *value,
46 				    GParamSpec    *pspec);
47 static void fo_property_get_property (GObject       *object,
48 				    guint          prop_id,
49 				    GValue        *value,
50 				    GParamSpec    *pspec);
51 static void fo_property_finalize    (GObject           *object);
52 
53 static FoDatatype* fo_property_get_value_default (FoProperty *property);
54 static void        fo_property_set_value_default (FoProperty *property,
55 					       FoDatatype *new_value);
56 static FoDatatype* fo_property_resolve_enum_default (const gchar *token,
57 						     FoContext   *context,
58 						     GError     **error);
59 static FoDatatype* fo_property_resolve_percent_default (gdouble           percentage,
60 							const FoDatatype *font_size,
61 							const FoFo       *fo_node,
62 							const FoContext  *context,
63 							GError          **err);
64 static FoProperty* fo_property_new_from_expr_default (FoPropertyClass *property_class,
65 						      const gchar *expr,
66 						      FoContext   *context,
67 						      FoProperty    *current_font_size,
68 						      FoFo *fo_node,
69 						      GError **error);
70 gchar* fo_property_sprintf         (FoObject *object);
71 static void fo_property_debug_dump (FoObject *object,
72 				    gint      depth);
73 static gpointer parent_class;
74 
75 GQuark
fo_property_error_quark(void)76 fo_property_error_quark (void)
77 {
78   static GQuark quark = 0;
79   if (quark == 0)
80     quark = g_quark_from_static_string ("Property error");
81   return quark;
82 }
83 
84 /**
85  * fo_property_get_type:
86  *
87  * Register the #FoProperty object type if not already registered and
88  * return its #GType value.
89  *
90  * Return value: #GType value of the #FoProperty object type.
91  **/
92 GType
fo_property_get_type(void)93 fo_property_get_type (void)
94 {
95   static GType object_type = 0;
96 
97   if (!object_type)
98     {
99       static const GTypeInfo object_info =
100       {
101         sizeof (FoPropertyClass),
102         (GBaseInitFunc) fo_property_base_init,
103         (GBaseFinalizeFunc) fo_property_base_finalize,
104         (GClassInitFunc) fo_property_class_init,
105         NULL,           /* class_finalize */
106         NULL,           /* class_data */
107         sizeof (FoProperty),
108         0,              /* n_preallocs */
109         NULL,		/* instance_init */
110 	NULL		/* value_table */
111       };
112 
113       object_type = g_type_register_static (FO_TYPE_OBJECT,
114                                             "FoProperty",
115                                             &object_info,
116 					    G_TYPE_FLAG_ABSTRACT);
117     }
118 
119   return object_type;
120 }
121 
122 /**
123  * fo_property_base_init:
124  * @klass: #FoPropertyClass object to initialise.
125  *
126  * Implements #GBaseInitFunc for #FoPropertyClass.
127  **/
128 void
fo_property_base_init(FoPropertyClass * klass)129 fo_property_base_init (FoPropertyClass *klass)
130 {
131   FoObjectClass *fo_object_class = FO_OBJECT_CLASS (klass);
132 
133   klass->is_inherited = FALSE;
134   klass->is_shorthand = FALSE;
135   klass->expr_env_list = fo_expr_env_list_new ();
136   klass->new_from_expr = fo_property_new_from_expr_default;
137   klass->expr_eval = fo_expr_eval;
138   klass->set_value = fo_property_set_value_default;
139   klass->get_value = fo_property_get_value_default;
140   klass->resolve_percent = fo_property_resolve_percent_default;
141 
142   fo_object_class->print_sprintf = fo_property_sprintf;
143   fo_object_class->debug_dump = fo_property_debug_dump;
144 }
145 
146 /**
147  * fo_property_base_finalize:
148  * @klass: #FoPropertyClass object to finalise.
149  *
150  * Implements #GBaseFinalizeFunc for #FoPropertyClass.
151  **/
152 void
fo_property_base_finalize(FoPropertyClass * klass)153 fo_property_base_finalize (FoPropertyClass *klass)
154 {
155   fo_expr_env_list_free (klass->expr_env_list);
156 }
157 
158 /**
159  * fo_property_class_init:
160  * @klass: #FoPropertyClass object to initialise.
161  *
162  * Implements #GClassInitFunc for #FoPropertyClass.
163  **/
164 void
fo_property_class_init(FoPropertyClass * klass)165 fo_property_class_init (FoPropertyClass *klass)
166 {
167   GObjectClass *object_class = G_OBJECT_CLASS (klass);
168 
169   parent_class = g_type_class_peek_parent (klass);
170 
171   object_class->finalize = fo_property_finalize;
172 
173   object_class->set_property = fo_property_set_property;
174   object_class->get_property = fo_property_get_property;
175 
176   g_object_class_install_property (object_class,
177                                    PROP_VALUE,
178                                    g_param_spec_object ("value",
179 							_("property value"),
180 							_("Property value"),
181 							FO_TYPE_DATATYPE,
182 							G_PARAM_READWRITE));
183   g_object_class_install_property
184     (object_class,
185      PROP_IS_INHERITED,
186      g_param_spec_boolean ("is-inherited",
187 			   _("Is inherited?"),
188 			   _("Is this an inherited property?"),
189 			   TRUE,
190 			   G_PARAM_READABLE));
191   g_object_class_install_property
192     (object_class,
193      PROP_IS_SHORTHAND,
194      g_param_spec_boolean ("is-shorthand",
195 			   _("Is shorthand?"),
196 			   _("Is this a shorthand property?"),
197 			   TRUE,
198 			   G_PARAM_READABLE));
199 
200   klass->resolve_enum = fo_property_resolve_enum_default;
201 }
202 
203 /**
204  * fo_property_finalize:
205  * @object: #FoProperty object to finalize.
206  *
207  * Implements #GObjectFinalizeFunc for #FoProperty.
208  **/
209 void
fo_property_finalize(GObject * object)210 fo_property_finalize (GObject *object)
211 {
212   FoProperty *property;
213 
214   property = FO_PROPERTY (object);
215 
216   if (property->value != NULL)
217     {
218       g_object_unref (property->value);
219       property->value = NULL;
220     }
221 
222   G_OBJECT_CLASS (parent_class)->finalize (object);
223 }
224 
225 
226 /**
227  * fo_property_set_property:
228  * @object:  #GObject whose property will be set.
229  * @prop_id: Property ID assigned when property registered.
230  * @value:   New value for property.
231  * @pspec:   Parameter specification for this property type.
232  *
233  * Implements #GObjectSetPropertyFunc for #FoProperty.
234  **/
235 void
fo_property_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)236 fo_property_set_property (GObject         *object,
237 			  guint            prop_id,
238 			  const GValue    *value,
239 			  GParamSpec      *pspec)
240 {
241   FoProperty *property;
242 
243   property = FO_PROPERTY (object);
244 
245   switch (prop_id)
246     {
247     case PROP_VALUE:
248       fo_property_set_value (property, g_value_get_object (value));
249       break;
250     default:
251       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
252       break;
253     }
254 }
255 
256 /**
257  * fo_property_get_property:
258  * @object:  #GObject whose property will be retreived.
259  * @prop_id: Property ID assigned when property registered.
260  * @value:   GValue to set with property value.
261  * @pspec:   Parameter specification for this property type.
262  *
263  * Implements #GObjectGetPropertyFunc for #FoProperty.
264  **/
265 void
fo_property_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)266 fo_property_get_property (GObject         *object,
267 			  guint            prop_id,
268 			  GValue          *value,
269 			  GParamSpec      *pspec)
270 {
271   FoProperty *property;
272 
273   property = FO_PROPERTY (object);
274 
275   switch (prop_id)
276     {
277     case PROP_VALUE:
278       g_value_set_instance (value,
279 			    fo_property_get_value (property));
280       break;
281     case PROP_IS_INHERITED:
282       g_value_set_boolean (value,
283 			   fo_property_is_inherited (property));
284       break;
285     case PROP_IS_SHORTHAND:
286       g_value_set_boolean (value,
287 			   fo_property_is_shorthand (property));
288       break;
289     default:
290       G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
291       break;
292     }
293 }
294 
295 /**
296  * fo_property_get_value:
297  * @property: #FoProperty object whose value is to be retrieved.
298  *
299  * Returns the current value property value of @property.
300  *
301  * Return value: The current 'value' property value.
302  **/
303 FoDatatype*
fo_property_get_value(FoProperty * property)304 fo_property_get_value (FoProperty *property)
305 {
306   g_return_val_if_fail (property != NULL, NULL);
307   g_return_val_if_fail (FO_IS_PROPERTY (property), NULL);
308 
309   return FO_PROPERTY_GET_CLASS (property)->get_value (property);
310 }
311 
312 /**
313  * fo_property_set_value:
314  * @property:  #FoProperty object whose value is to be set.
315  * @new_value: New value for the property.
316  *
317  * Sets the 'value' property of @property.
318  **/
319 void
fo_property_set_value(FoProperty * property,FoDatatype * new_value)320 fo_property_set_value (FoProperty *property,
321 		       FoDatatype *new_value)
322 {
323   g_return_if_fail (property != NULL);
324   g_return_if_fail (FO_IS_PROPERTY (property));
325 
326   FO_PROPERTY_GET_CLASS (property)->set_value (property, new_value);
327 }
328 
329 /**
330  * fo_property_get_value_default:
331  * @property: FoProperty object whose value is to be retrieved
332  *
333  * Returns the current #value property value of @property
334  *
335  * Return value: The current #value property value
336  **/
337 FoDatatype*
fo_property_get_value_default(FoProperty * property)338 fo_property_get_value_default (FoProperty *property)
339 {
340   g_return_val_if_fail (property != NULL, NULL);
341   g_return_val_if_fail (FO_IS_PROPERTY (property), NULL);
342 
343   return property->value;
344 }
345 
346 /**
347  * fo_property_set_value_default:
348  * @property:  FoProperty object whose value is to be set
349  * @new_value: New value for the property
350  *
351  * Sets the #value property of @property
352  **/
353 void
fo_property_set_value_default(FoProperty * property,FoDatatype * new_value)354 fo_property_set_value_default (FoProperty *property,
355 			       FoDatatype *new_value)
356 {
357   g_return_if_fail (property != NULL);
358   g_return_if_fail (FO_IS_PROPERTY (property));
359   g_return_if_fail (new_value == NULL || FO_IS_DATATYPE (new_value));
360 
361   if (new_value != NULL)
362     g_object_ref (G_OBJECT (new_value));
363   if (property->value != NULL)
364     g_object_unref (G_OBJECT (property->value));
365   property->value = new_value;
366   /*g_object_notify(G_OBJECT(property), "value");*/
367 }
368 
369 /**
370  * fo_property_resolve_enum_default:
371  * @token:
372  * @context:
373  * @error:
374  *
375  *
376  *
377  * Return value:
378  **/
379 FoDatatype*
fo_property_resolve_enum_default(const gchar * token G_GNUC_UNUSED,FoContext * context G_GNUC_UNUSED,GError ** error)380 fo_property_resolve_enum_default (const gchar *token G_GNUC_UNUSED,
381 				  FoContext   *context G_GNUC_UNUSED,
382 				  GError     **error)
383 {
384   g_warning ("This property doesn't have any enumerated values.\n");
385 
386   g_set_error (error,
387 	       FO_PROPERTY_ERROR,
388 	       FO_PROPERTY_ERROR_NO_ENUMERATION,
389 	       "%s",
390 	       fo_property_error_messages[FO_PROPERTY_ERROR_NO_ENUMERATION]);
391   return NULL;
392 }
393 
394 /**
395  * fo_property_resolve_percent_default:
396  * @percentage: Percentage value to resolve.
397  * @font_size:  Font size to use if a percentage of font-size.
398  * @fo_node:    Current #FoFo.
399  * @context:    #FoContext of parent #FoFo.
400  * @err:        Indicates whether an error occurs.
401  *
402  * Resolves @percentage as a percentage of a known value which,
403  * depending on the property, could be the current font-size value or
404  * some property value of the current #FoFo or its first #FoArea.
405  *
406  * Return value: #FoDatatype representing resolved value.
407  **/
408 FoDatatype*
fo_property_resolve_percent_default(gdouble percentage,const FoDatatype * font_size G_GNUC_UNUSED,const FoFo * fo_node G_GNUC_UNUSED,const FoContext * context G_GNUC_UNUSED,GError ** err G_GNUC_UNUSED)409 fo_property_resolve_percent_default (gdouble            percentage,
410 				     const FoDatatype  *font_size G_GNUC_UNUSED,
411 				     const FoFo        *fo_node G_GNUC_UNUSED,
412 				     const FoContext   *context G_GNUC_UNUSED,
413 				     GError           **err G_GNUC_UNUSED)
414 {
415   FoDatatype *percentage_datatype;
416 
417   percentage_datatype = fo_percentage_new ();
418   fo_percentage_set_value (percentage_datatype,
419 			   percentage);
420 
421   return percentage_datatype;
422 }
423 
424 /**
425  * fo_property_new_from_string:
426  * @property_class:    #FoPropertyClass or subclass of property.
427  * @expr:              Expression to be evaluated as a string.
428  * @context:           #FoContext for inherited values.
429  * @current_font_size: Current font size for resolving 'em' values.
430  * @fo_node:           The current #FoFo node.
431  * @error:             #GError for indicating any error that occurs.
432  *
433  * Evaluate @expr and create a new instance of @property_class with
434  * value of @expr.
435  *
436  * Other parameters (except @error) provide context for evaluating
437  * @expr.
438  *
439  * Return value: A new instance of @property_class, or NULL if error.
440  **/
441 FoProperty*
fo_property_new_from_string(FoPropertyClass * property_class,const gchar * expr,FoContext * context,FoProperty * current_font_size,FoFo * fo_node G_GNUC_UNUSED,GError ** error)442 fo_property_new_from_string (FoPropertyClass *property_class,
443 			     const gchar *expr,
444 			     FoContext   *context,
445 			     FoProperty    *current_font_size,
446 			     FoFo *fo_node G_GNUC_UNUSED,
447 			     GError **error)
448 {
449   FoProperty *property;
450   FoDatatype *datatype;
451   GError *tmp_error = NULL;
452   const gchar *property_name = NULL;
453 
454   g_return_val_if_fail (FO_IS_PROPERTY_CLASS (property_class), NULL);
455   g_return_val_if_fail (expr != NULL, NULL);
456   g_return_val_if_fail (context != NULL, NULL);
457   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
458   g_return_val_if_fail
459     (current_font_size == NULL || FO_IS_PROPERTY_FONT_SIZE (current_font_size),
460      NULL);
461   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
462 
463   property_name = G_OBJECT_CLASS_NAME (property_class);
464 
465   datatype = fo_string_new_with_value (expr);
466 
467   datatype = property_class->validate (datatype, context, &tmp_error);
468 
469   if (tmp_error != NULL)
470     {
471       g_propagate_error (error, tmp_error);
472       return NULL;
473     }
474 
475   property =
476     (FoProperty *) g_object_new (G_OBJECT_CLASS_TYPE (property_class),
477 				 "value",
478 				 datatype,
479 				 NULL);
480 
481   return property;
482 }
483 
484 /**
485  * fo_property_new_from_expr_default:
486  * @property_class:    #FoPropertyClass or subclass of property.
487  * @expr:              Expression to be evaluated.
488  * @context:           #FoContext for inherited values.
489  * @current_font_size: Current font size for resolving 'em' values.
490  * @fo_node:           The current #FoFo node.
491  * @error:             #GError for indicating any error that occurs.
492  *
493  * Evaluate @expr and create a new instance of @property_class with
494  * value of @expr.
495  *
496  * Other parameters (except @error) provide context for evaluating
497  * @expr.
498  *
499  * Return value: A new instance of @property_class, or NULL if error.
500  **/
501 FoProperty*
fo_property_new_from_expr_default(FoPropertyClass * property_class,const gchar * expr,FoContext * context,FoProperty * current_font_size,FoFo * fo_node,GError ** error)502 fo_property_new_from_expr_default (FoPropertyClass *property_class,
503 				   const gchar *expr,
504 				   FoContext   *context,
505 				   FoProperty    *current_font_size,
506 				   FoFo *fo_node,
507 				   GError **error)
508 {
509   GError *tmp_error = NULL;
510 
511   g_return_val_if_fail (FO_IS_PROPERTY_CLASS (property_class), NULL);
512   g_return_val_if_fail (expr != NULL, NULL);
513   g_return_val_if_fail (context != NULL, NULL);
514   g_return_val_if_fail (FO_IS_CONTEXT (context), NULL);
515   g_return_val_if_fail
516     (current_font_size == NULL || FO_IS_PROPERTY_FONT_SIZE (current_font_size),
517      NULL);
518   g_return_val_if_fail (error == NULL || *error == NULL, NULL);
519 
520   const gchar *property_name = G_OBJECT_CLASS_NAME (property_class);
521 
522   FoDatatype *datatype =
523     property_class->expr_eval (expr,
524 			       property_name,
525 			       property_class->resolve_enum,
526 			       property_class->resolve_percent,
527 			       current_font_size,
528 			       fo_node,
529 			       context,
530 			       property_class->expr_env_list,
531 			       &tmp_error);
532 
533   if (tmp_error != NULL)
534     {
535       g_propagate_error (error, tmp_error);
536       return NULL;
537     }
538 
539   datatype = property_class->validate (datatype, context, &tmp_error);
540 
541   if (tmp_error != NULL)
542     {
543       g_propagate_error (error, tmp_error);
544       return NULL;
545     }
546 
547   g_object_ref_sink (datatype);
548 
549   FoProperty *property =
550     (FoProperty *) g_object_new (G_OBJECT_CLASS_TYPE (property_class),
551 				 "value",
552 				 datatype,
553 				 NULL);
554 
555   return property;
556 }
557 
558 /**
559  * fo_property_new_from_expr:
560  * @property_class:    Class of property for which to evaluate expression.
561  * @expr:              Expression to evaluate.
562  * @context:           Current #FoContext.
563  * @current_font_size: Current "font-size" value
564  * @fo_node:           Current FO
565  * @error:             Indication of any error that occurred
566  *
567  * Evaluates @expr as a value of an instance of @property_class.
568  * The other parameters provide the context for evaluating @expr.
569  *
570  * Returns: New instance of @property_class, or %NULL if an
571  *          error ocurred.
572  **/
573 FoProperty*
fo_property_new_from_expr(FoPropertyClass * property_class,const gchar * expr,FoContext * context,FoProperty * current_font_size,FoFo * fo_node,GError ** error)574 fo_property_new_from_expr (FoPropertyClass *property_class,
575 			   const gchar     *expr,
576 			   FoContext       *context,
577 			   FoProperty      *current_font_size,
578 			   FoFo            *fo_node,
579 			   GError         **error)
580 {
581   g_return_val_if_fail (FO_IS_PROPERTY_CLASS (property_class), NULL);
582 
583   if (*expr == '\0')
584     {
585       const gchar *property_name = G_OBJECT_CLASS_NAME (property_class);
586 
587       g_set_error (error,
588 		   FO_PROPERTY_ERROR,
589 		   FO_PROPERTY_ERROR_ZERO_LENGTH,
590 		   fo_property_error_messages[FO_PROPERTY_ERROR_ZERO_LENGTH],
591 		   property_name);
592 
593       return NULL;
594     }
595 
596   return property_class->new_from_expr (property_class,
597 					expr,
598 					context,
599 					current_font_size,
600 					fo_node,
601 					error);
602 }
603 /**
604  * fo_property_class_is_inherited:
605  * @property_class: #FoPropertyClass or a subclass of #FoPropertyClass.
606  *
607  * Indicates whether the XSL property represented by @property_class
608  * is defined in the XSL 1.0 Recommendation as an inherited property.
609  *
610  * Return value: TRUE if @property_class is inherited, FALSE if not.
611  **/
612 gboolean
fo_property_class_is_inherited(FoPropertyClass * property_class)613 fo_property_class_is_inherited (FoPropertyClass *property_class)
614 {
615   g_return_val_if_fail (FO_IS_PROPERTY_CLASS (property_class), FALSE);
616 
617   return (FO_PROPERTY_CLASS (property_class)->is_inherited);
618 }
619 
620 /**
621  * fo_property_is_inherited:
622  * @property: #FoProperty or subclass of #FoProperty
623  *
624  * Indicates whether the XSL property represented by @property is
625  * defined in the XSL 1.0 Recommendation as an inherited property.
626  *
627  * Return value: TRUE if @property is inherited, FALSE otherwise
628  **/
629 gboolean
fo_property_is_inherited(FoProperty * property)630 fo_property_is_inherited (FoProperty *property)
631 {
632   g_return_val_if_fail (FO_IS_PROPERTY (property), FALSE);
633 
634   return fo_property_class_is_inherited (FO_PROPERTY_GET_CLASS (property));
635 }
636 
637 /**
638  * fo_property_class_is_shorthand:
639  * @property_class: #FoPropertyClass or a subclass of #FoPropertyClass.
640  *
641  * Indicates whether the XSL property represented by @property_class
642  * is defined in the XSL 1.0 Recommendation as a shorthand property.
643  *
644  * Return value: TRUE if @property_class is a shorthand, FALSE if not.
645  **/
646 gboolean
fo_property_class_is_shorthand(FoPropertyClass * property_class)647 fo_property_class_is_shorthand (FoPropertyClass *property_class)
648 {
649   g_return_val_if_fail (FO_IS_PROPERTY_CLASS (property_class), FALSE);
650 
651   return (FO_PROPERTY_CLASS (property_class)->is_shorthand);
652 }
653 
654 /**
655  * fo_property_is_shorthand:
656  * @property: #FoProperty or a subclass of #FoProperty.
657  *
658  * Indicates whether the XSL property represented by @property is
659  * defined in the XSL 1.0 Recommendation as a shorthand property.
660  *
661  * Return value: TRUE if @property is a shorthand, FALSE otherwise
662  **/
663 gboolean
fo_property_is_shorthand(FoProperty * property)664 fo_property_is_shorthand (FoProperty *property)
665 {
666   g_return_val_if_fail (FO_IS_PROPERTY (property), FALSE);
667 
668   return fo_property_class_is_shorthand (FO_PROPERTY_GET_CLASS (property));
669 }
670 
671 /**
672  * fo_property_sprintf:
673  * @object: Object to be named
674  *
675  * Returns a string representing the property and its current value.
676  * The returned value should be freed when no longer needed.
677  *
678  * Return value: A newly allocated string
679  **/
680 gchar*
fo_property_sprintf(FoObject * object)681 fo_property_sprintf (FoObject *object)
682 {
683   g_return_val_if_fail (object != NULL, NULL);
684   g_return_val_if_fail (FO_IS_PROPERTY (object), NULL);
685 
686   return
687     g_strdup_printf ("%s: %s",
688 		     g_type_name (G_TYPE_FROM_INSTANCE (object)),
689 		     fo_object_sprintf (FO_PROPERTY (object)->value));
690 }
691 
692 /**
693  * fo_property_debug_dump:
694  * @object:
695  * @depth:
696  *
697  *
698  **/
699 void
fo_property_debug_dump(FoObject * object,gint depth)700 fo_property_debug_dump (FoObject *object, gint depth)
701 {
702   gchar *indent = g_strnfill (depth * 2, ' ');
703   gchar* object_sprintf;
704 
705   g_return_if_fail (object != NULL);
706   g_return_if_fail (FO_IS_PROPERTY (object));
707 
708   object_sprintf = fo_object_debug_sprintf (object);
709 
710   g_log (G_LOG_DOMAIN,
711 	 G_LOG_LEVEL_DEBUG,
712 	 "%s%s",
713 	 indent,
714 	 object_sprintf);
715 
716   g_free (object_sprintf);
717   g_free (indent);
718 
719   fo_object_debug_dump (fo_property_get_value (FO_PROPERTY (object)),
720 			depth + 2);
721 }
722