1 /* Fo
2 * fo-keep.c: Keep datatype
3 *
4 * Copyright (C) 2001 Sun Microsystems
5 * Copyright (C) 2007-2010 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include "fo-utils.h"
11 #include "fo-datatype.h"
12 #include "fo-datatype-private.h"
13 #include "fo-keep.h"
14 #include "fo-enum.h"
15 #include "fo-length.h"
16 #include "fo-integer.h"
17 #include "fo-percentage.h"
18 #include "fo-boolean.h"
19
20 enum {
21 PROP_0,
22 PROP_WITHIN_LINE,
23 PROP_WITHIN_COLUMN,
24 PROP_WITHIN_PAGE
25 };
26
27 struct _FoKeep
28 {
29 FoDatatype parent_instance;
30
31 FoDatatype *within_line;
32 FoDatatype *within_column;
33 FoDatatype *within_page;
34 };
35
36 struct _FoKeepClass
37 {
38 FoDatatypeClass parent_class;
39
40 };
41
42 static void _init (FoKeep *keep);
43 static void _class_init (FoKeepClass *klass);
44 static void _set_property (GObject *object,
45 guint prop_id,
46 const GValue *value,
47 GParamSpec *pspec);
48 static void _get_property (GObject *object,
49 guint prop_id,
50 GValue *value,
51 GParamSpec *pspec);
52 static void _dispose (GObject *object);
53
54 static gchar* _sprintf (FoObject *object);
55 static FoDatatype * _copy (FoDatatype *datatype);
56 static void _set_within_line (FoDatatype *keep,
57 FoDatatype *new_within_line);
58 static void _set_within_column (FoDatatype *keep,
59 FoDatatype *new_within_column);
60 static void _set_within_page (FoDatatype *keep,
61 FoDatatype *new_within_page);
62
63 static gpointer parent_class;
64
65 /**
66 * fo_keep_get_type:
67 *
68 * Register the #FoKeep object type.
69 *
70 * Return value: GType value of the #FoKeep object type.
71 **/
72 GType
fo_keep_get_type(void)73 fo_keep_get_type (void)
74 {
75 static GType object_type = 0;
76
77 if (!object_type)
78 {
79 static const GTypeInfo object_info =
80 {
81 sizeof (FoKeepClass),
82 NULL, /* base_init */
83 NULL, /* base_finalize */
84 (GClassInitFunc) _class_init,
85 NULL, /* class_finalize */
86 NULL, /* class_data */
87 sizeof (FoKeep),
88 0, /* n_preallocs */
89 (GInstanceInitFunc) _init,
90 NULL /* value_table */
91 };
92
93 object_type = g_type_register_static (FO_TYPE_DATATYPE,
94 "FoKeep",
95 &object_info, 0);
96 }
97
98 return object_type;
99 }
100
101 /**
102 * _init:
103 * @keep: #FoKeep object to initialise
104 *
105 * Implements GInstanceInitFunc for #FoKeep
106 **/
107 void
_init(FoKeep * keep)108 _init (FoKeep *keep)
109 {
110 keep->within_page =
111 g_object_ref (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_AUTO));
112 keep->within_column =
113 g_object_ref (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_AUTO));
114 keep->within_line =
115 g_object_ref (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_AUTO));
116 }
117
118 /**
119 * _class_init:
120 * @klass: FoKeepClass object to initialise
121 *
122 * Implements GClassInitFunc for FoKeepClass
123 **/
124 void
_class_init(FoKeepClass * klass)125 _class_init (FoKeepClass *klass)
126 {
127 GObjectClass *object_class = G_OBJECT_CLASS (klass);
128
129 parent_class = g_type_class_peek_parent (klass);
130
131 object_class->dispose = _dispose;
132
133 object_class->set_property = _set_property;
134 object_class->get_property = _get_property;
135
136 FO_DATATYPE_CLASS (klass)->copy = _copy;
137 FO_OBJECT_CLASS (klass)->print_sprintf = _sprintf;
138
139 g_object_class_install_property (object_class,
140 PROP_WITHIN_LINE,
141 g_param_spec_object ("within-line",
142 _("Within Line"),
143 _("Keep within line value"),
144 FO_TYPE_DATATYPE,
145 G_PARAM_READWRITE |
146 G_PARAM_CONSTRUCT_ONLY));
147
148 g_object_class_install_property (object_class,
149 PROP_WITHIN_COLUMN,
150 g_param_spec_object ("within-column",
151 _("Within Column"),
152 _("Keep within column value"),
153 FO_TYPE_DATATYPE,
154 G_PARAM_READWRITE |
155 G_PARAM_CONSTRUCT_ONLY));
156
157 g_object_class_install_property (object_class,
158 PROP_WITHIN_PAGE,
159 g_param_spec_object ("within-page",
160 _("Within Page"),
161 _("Keep within page value"),
162 FO_TYPE_DATATYPE,
163 G_PARAM_READWRITE |
164 G_PARAM_CONSTRUCT_ONLY));
165
166
167 }
168
169 /**
170 * _dispose:
171 * @object: FoKeep object to dispose
172 *
173 * Implements GObjectDisposeFunc for FoKeep
174 **/
175 void
_dispose(GObject * object)176 _dispose (GObject *object)
177 {
178 FoKeep *keep = FO_KEEP (object);
179
180 if (keep->within_page != NULL)
181 {
182 g_object_unref (keep->within_page);
183 keep->within_page = NULL;
184 }
185
186 if (keep->within_column != NULL)
187 {
188 g_object_unref (keep->within_column);
189 keep->within_column = NULL;
190 }
191
192 if (keep->within_line != NULL)
193 {
194 g_object_unref (keep->within_line);
195 keep->within_line = NULL;
196 }
197
198 G_OBJECT_CLASS (parent_class)->dispose (object);
199 }
200
201
202 /**
203 * _get_property:
204 * @object: GObject whose property will be retreived
205 * @prop_id: Property ID assigned when property registered
206 * @value: GValue to set with property value
207 * @pspec: Parameter specification for this property type
208 *
209 * Implements #GObjectGetPropertyFunc for FoKeep
210 **/
211 void
_get_property(GObject * object,guint prop_id,GValue * value,GParamSpec * pspec)212 _get_property (GObject *object,
213 guint prop_id,
214 GValue *value,
215 GParamSpec *pspec)
216 {
217 FoDatatype *keep;
218
219 keep = FO_DATATYPE (object);
220
221 switch (prop_id)
222 {
223 case PROP_WITHIN_LINE:
224 g_value_set_object (value, fo_keep_get_within_line (keep));
225 break;
226 case PROP_WITHIN_COLUMN:
227 g_value_set_object (value, fo_keep_get_within_column (keep));
228 break;
229 case PROP_WITHIN_PAGE:
230 g_value_set_object (value, fo_keep_get_within_page (keep));
231 break;
232 default:
233 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
234 break;
235 }
236 }
237
238 /**
239 * _set_property:
240 * @object: GObject whose property will be set
241 * @prop_id: Property ID assigned when property registered
242 * @value: New value for property
243 * @pspec: Parameter specification for this property type
244 *
245 * Implements #GObjectSetPropertyFunc for FoKeep
246 **/
247 void
_set_property(GObject * object,guint prop_id,const GValue * value,GParamSpec * pspec)248 _set_property (GObject *object,
249 guint prop_id,
250 const GValue *value,
251 GParamSpec *pspec)
252 {
253 FoDatatype *keep;
254
255 keep = FO_DATATYPE (object);
256
257 switch (prop_id)
258 {
259 case PROP_WITHIN_LINE:
260 _set_within_line (keep, g_value_get_object (value));
261 break;
262 case PROP_WITHIN_COLUMN:
263 _set_within_column (keep, g_value_get_object (value));
264 break;
265 case PROP_WITHIN_PAGE:
266 _set_within_page (keep, g_value_get_object (value));
267 break;
268 default:
269 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
270 break;
271 }
272 }
273
274 /**
275 * fo_keep_new:
276 *
277 * Creates a new #FoKeep initialized to default value.
278 *
279 * Return value: the new #FoKeep
280 **/
281 FoDatatype *
fo_keep_new(void)282 fo_keep_new (void)
283 {
284 return FO_DATATYPE (g_object_new (fo_keep_get_type (),
285 NULL));
286 }
287
288 /**
289 * fo_keep_new_with_value:
290 * @value: Keep of the new #FoKeep
291 *
292 * Creates a new #FoKeep set to @value
293 *
294 * Return value: The new #FoKeep
295 **/
296 FoDatatype *
fo_keep_new_with_value(FoDatatype * value)297 fo_keep_new_with_value (FoDatatype *value)
298 {
299 FoDatatype *keep = fo_keep_new ();
300
301 _set_within_page (keep, value);
302 _set_within_column (keep, value);
303 _set_within_line (keep, value);
304
305 return keep;
306 }
307
308 /**
309 * fo_keep_get_keep_auto:
310 *
311 * Creates a new #FoKeep set to .within-line="auto",
312 * .within-column="auto", and .within-page="auto".
313 *
314 * Return value: The new #FoKeep
315 **/
316 FoDatatype*
fo_keep_get_keep_auto(void)317 fo_keep_get_keep_auto (void)
318 {
319 static FoDatatype *keep = NULL;
320
321 if (keep == NULL)
322 {
323 keep = fo_keep_new ();
324 }
325
326 return keep;
327 }
328
329 /**
330 * fo_keep_get_keep_always:
331 *
332 * Creates a new #FoKeep set to .within-line="always",
333 * .within-column="always", and .within-page="always".
334 *
335 * Return value: The new #FoKeep
336 **/
337 FoDatatype *
fo_keep_get_keep_always(void)338 fo_keep_get_keep_always (void)
339 {
340 static FoDatatype *keep = NULL;
341
342 if (keep == NULL)
343 {
344 keep =
345 fo_keep_new_with_value (fo_enum_factory_get_enum_by_value (FO_ENUM_ENUM_ALWAYS));
346 }
347
348 return keep;
349 }
350
351 /**
352 * fo_keep_get_within_page:
353 * @datatype: #FoKeep
354 *
355 * Gets the .within-page component value of @datatype
356 *
357 * Return value: The .within-page value of @datatype
358 **/
359 FoDatatype *
fo_keep_get_within_page(FoDatatype * datatype)360 fo_keep_get_within_page (FoDatatype *datatype)
361 {
362 g_return_val_if_fail (datatype != NULL, NULL);
363 g_return_val_if_fail (FO_IS_KEEP (datatype), 0);
364
365 return FO_KEEP (datatype)->within_page;
366 }
367
368 /**
369 * _set_within_page:
370 * @datatype: #FoKeep
371 * @new_within_page: New .within-page value
372 *
373 * Sets the .within-page component of @datatype
374 **/
375 static void
_set_within_page(FoDatatype * datatype,FoDatatype * new_within_page)376 _set_within_page (FoDatatype *datatype,
377 FoDatatype *new_within_page)
378 {
379 FoKeep *keep = (FoKeep *) datatype;
380
381 g_return_if_fail (keep != NULL);
382 g_return_if_fail (FO_IS_KEEP (keep));
383 g_return_if_fail ((new_within_page == NULL) ||
384 FO_IS_DATATYPE (new_within_page));
385
386 if (new_within_page != NULL)
387 {
388 g_object_ref (new_within_page);
389 }
390 if (keep->within_page != NULL)
391 {
392 g_object_unref (keep->within_page);
393 }
394
395 keep->within_page = new_within_page;
396 /*g_object_notify(G_OBJECT(keep), "within-page");*/
397 }
398
399 /**
400 * fo_keep_get_within_column:
401 * @datatype: #FoKeep
402 *
403 * Gets the .within-column component value of @datatype
404 *
405 * Return value: The .within-column value of @datatype
406 **/
407 FoDatatype *
fo_keep_get_within_column(FoDatatype * datatype)408 fo_keep_get_within_column (FoDatatype *datatype)
409 {
410 g_return_val_if_fail (datatype != NULL, NULL);
411 g_return_val_if_fail (FO_IS_KEEP (datatype), 0);
412
413 return FO_KEEP (datatype)->within_column;
414 }
415
416 /**
417 * _set_within_column:
418 * @datatype: #FoKeep
419 * @new_within_column: New .within-column value
420 *
421 * Sets the .within-column component of @datatype
422 **/
423 static void
_set_within_column(FoDatatype * datatype,FoDatatype * new_within_column)424 _set_within_column (FoDatatype *datatype,
425 FoDatatype *new_within_column)
426 {
427 FoKeep *keep = (FoKeep *) datatype;
428
429 g_return_if_fail (keep != NULL);
430 g_return_if_fail (FO_IS_KEEP (keep));
431 g_return_if_fail ((new_within_column == NULL) ||
432 FO_IS_DATATYPE (new_within_column));
433
434 if (new_within_column != NULL)
435 {
436 g_object_ref (new_within_column);
437 }
438
439 if (keep->within_column != NULL)
440 {
441 g_object_unref (keep->within_column);
442 }
443
444 keep->within_column = new_within_column;
445 /*g_object_notify(G_OBJECT(keep), "within-column");*/
446 }
447
448 /**
449 * fo_keep_get_within_line:
450 * @datatype: #FoKeep
451 *
452 * Gets the .within-line component value of @datatype
453 *
454 * Return value: The .within-line value of @datatype
455 **/
456 FoDatatype *
fo_keep_get_within_line(FoDatatype * datatype)457 fo_keep_get_within_line (FoDatatype *datatype)
458 {
459 g_return_val_if_fail (datatype != NULL, NULL);
460 g_return_val_if_fail (FO_IS_KEEP (datatype), 0);
461
462 return FO_KEEP (datatype)->within_line;
463 }
464
465 /**
466 * _set_within_line:
467 * @datatype: #FoKeep
468 * @new_within_line: New .within-line value
469 *
470 * Sets the .within-line component of @datatype
471 **/
472 static void
_set_within_line(FoDatatype * datatype,FoDatatype * new_within_line)473 _set_within_line (FoDatatype *datatype,
474 FoDatatype *new_within_line)
475 {
476 FoKeep *keep = (FoKeep *) datatype;
477
478 g_return_if_fail (keep != NULL);
479 g_return_if_fail (FO_IS_KEEP (keep));
480 g_return_if_fail ((new_within_line == NULL) ||
481 FO_IS_DATATYPE (new_within_line));
482
483 if (new_within_line != NULL)
484 {
485 g_object_ref (new_within_line);
486 }
487
488 if (keep->within_line != NULL)
489 {
490 g_object_unref (keep->within_line);
491 }
492
493 keep->within_line = new_within_line;
494 /*g_object_notify(G_OBJECT(keep), "within-line");*/
495 }
496
497 /**
498 * _sprintf:
499 * @object:
500 *
501 *
502 *
503 * Returns:
504 **/
505 static gchar*
_sprintf(FoObject * object)506 _sprintf (FoObject *object)
507 {
508 g_return_val_if_fail (object != NULL, NULL);
509 g_return_val_if_fail (FO_IS_KEEP (object), NULL);
510
511 gchar *within_page = fo_object_sprintf (FO_KEEP (object)->within_page);
512 gchar *within_column = fo_object_sprintf (FO_KEEP (object)->within_column);
513 gchar *within_line = fo_object_sprintf (FO_KEEP (object)->within_line);
514
515 gchar *string = g_strdup_printf ("page: %s; column: %s; line: %s",
516 within_page,
517 within_column,
518 within_line);
519
520 g_free (within_line);
521 g_free (within_column);
522 g_free (within_page);
523
524 return string;
525 }
526
527 /**
528 * _copy:
529 * @datatype: Source #FoKeep
530 *
531 * Creates a copy of @datatype
532 *
533 * Return value: Copy of @datatype
534 **/
535 static FoDatatype *
_copy(FoDatatype * datatype)536 _copy (FoDatatype *datatype)
537 {
538 FoDatatype* keep;
539
540 g_return_val_if_fail (datatype != NULL, NULL);
541 g_return_val_if_fail (FO_IS_KEEP (datatype), NULL);
542
543 keep = fo_keep_new ();
544 FO_KEEP (keep)->within_page =
545 FO_KEEP (datatype)->within_page;
546 FO_KEEP (keep)->within_column =
547 FO_KEEP (datatype)->within_column;
548 FO_KEEP (keep)->within_line =
549 FO_KEEP (datatype)->within_line;
550
551 return (keep);
552 }
553
554 /**
555 * fo_keep_resolve:
556 * @shortform: Single-value short form of the keep, or
557 * NULL
558 * @within_line: .within-line component of the keep, or NULL
559 * @within_column: .within-column component of the keep, or NULL
560 * @within_page: .within-page component of the keep, or NULL
561 * @error: GError used for reporting errors
562 *
563 * Resolve the shortform and components of the keep in
564 * accordance with Section 5.11, Datatypes, of the XSL 1.0
565 * Recommendation.
566 *
567 * Does not change the ref-count of any FoDatatype arguments.
568 *
569 * Return value: Compound keep datatype, or NULL if an error
570 * occurred
571 **/
572 FoDatatype *
fo_keep_resolve(FoDatatype * shortform,FoDatatype * within_line,FoDatatype * within_column,FoDatatype * within_page,GError ** error G_GNUC_UNUSED)573 fo_keep_resolve (FoDatatype *shortform,
574 FoDatatype *within_line,
575 FoDatatype *within_column,
576 FoDatatype *within_page,
577 GError **error G_GNUC_UNUSED)
578 {
579 FoDatatype *use_keep;
580
581 g_return_val_if_fail (shortform == NULL ||
582 FO_IS_KEEP (shortform),
583 NULL);
584 g_return_val_if_fail (within_line == NULL ||
585 FO_IS_INTEGER (within_line) ||
586 (FO_IS_ENUM (within_line) &&
587 ((fo_enum_get_value (within_line) ==
588 FO_ENUM_ENUM_AUTO) ||
589 (fo_enum_get_value (within_line) ==
590 FO_ENUM_ENUM_ALWAYS))),
591 NULL);
592 g_return_val_if_fail (within_column == NULL ||
593 FO_IS_INTEGER (within_column) ||
594 (FO_IS_ENUM (within_column) &&
595 ((fo_enum_get_value (within_column) ==
596 FO_ENUM_ENUM_AUTO) ||
597 (fo_enum_get_value (within_column) ==
598 FO_ENUM_ENUM_ALWAYS))),
599 NULL);
600 g_return_val_if_fail (within_page == NULL ||
601 FO_IS_INTEGER (within_page) ||
602 (FO_IS_ENUM (within_page) &&
603 ((fo_enum_get_value (within_page) ==
604 FO_ENUM_ENUM_AUTO) ||
605 (fo_enum_get_value (within_page) ==
606 FO_ENUM_ENUM_ALWAYS))),
607 NULL);
608
609 if (FO_IS_KEEP (shortform) &&
610 within_line == NULL &&
611 within_column == NULL &&
612 within_page == NULL)
613 {
614 use_keep = shortform;
615 }
616 else
617 {
618 if (shortform == NULL)
619 {
620 use_keep = fo_keep_new ();
621 }
622 else
623 {
624 use_keep = _copy (shortform);
625 }
626
627 if (within_line != NULL)
628 {
629 _set_within_line (use_keep,
630 within_line);
631 }
632
633 if (within_column != NULL)
634 {
635 _set_within_column (use_keep,
636 within_column);
637 }
638
639 if (within_page != NULL)
640 {
641 _set_within_page (use_keep,
642 within_page);
643 }
644 }
645
646 return use_keep;
647 }
648