1 /* Fo
2 * fo-area-table-continuation.c: Area object for 'table-continuation' formatting objects
3 *
4 * Copyright (C) 2001 Sun Microsystems
5 * Copyright (C) 2007-2009 Menteith Consulting Ltd
6 *
7 * See COPYING for the status of this software.
8 */
9
10 #include "fo-utils.h"
11 #include "fo-area.h"
12 #include "fo-area-private.h"
13 #include "fo-area-reference.h"
14 #include "fo-area-reference-private.h"
15 #include "fo-area-table-continuation.h"
16 #include "fo-area-table-continuation-private.h"
17 #include "fo-area-table-header.h"
18 #include "fo/fo-block-fo.h"
19 #include "fo/fo-table.h"
20 #include "property/fo-property-block-progression-dimension.h"
21 #include "property/fo-property-inline-progression-dimension.h"
22 #include "property/fo-property-keep-with-next.h"
23 #include "property/fo-property-keep-with-previous.h"
24 #include "property/fo-property-keep-with-next-within-column.h"
25 #include "property/fo-property-keep-with-next-within-page.h"
26 #include "property/fo-property-keep-with-previous-within-column.h"
27 #include "property/fo-property-keep-with-previous-within-page.h"
28
29 static void fo_area_table_continuation_class_init (FoAreaTableContinuationClass *klass);
30 static void fo_area_table_continuation_finalize (GObject *object);
31
32 static void fo_area_table_continuation_debug_dump_properties (FoArea *area,
33 gint depth);
34 static FoArea* fo_area_table_continuation_size_request (FoArea *child);
35 static FoArea* fo_area_table_continuation_split_before_height (FoArea *area,
36 gdouble max_height);
37 static gboolean fo_area_table_continuation_split_before_height_check (FoArea *area,
38 gdouble max_height);
39 static void fo_area_table_continuation_size_adjust (FoArea *area,
40 gpointer data);
41
42 static void fo_area_table_continuation_set_or_split (FoArea *area,
43 gpointer data);
44 static void fo_area_table_continuation_update_after_clone (FoArea *clone,
45 FoArea *original);
46
47 static gpointer parent_class;
48
49 /**
50 * fo_area_table_continuation_get_type:
51 * @void:
52 *
53 * Register the FoAreaTableContinuation object type.
54 *
55 * Return value: GType value of the FoAreaTableContinuation object type.
56 **/
57 GType
fo_area_table_continuation_get_type(void)58 fo_area_table_continuation_get_type (void)
59 {
60 static GType object_type = 0;
61
62 if (!object_type)
63 {
64 static const GTypeInfo object_info =
65 {
66 sizeof (FoAreaTableContinuationClass),
67 (GBaseInitFunc) NULL,
68 (GBaseFinalizeFunc) NULL,
69 (GClassInitFunc) fo_area_table_continuation_class_init,
70 NULL, /* class_finalize */
71 NULL, /* class_data */
72 sizeof (FoAreaTableContinuation),
73 0, /* n_preallocs */
74 NULL, /* instance_init */
75 NULL /* value_table */
76 };
77
78 object_type = g_type_register_static (FO_TYPE_AREA_TABLE,
79 "FoAreaTableContinuation",
80 &object_info, 0);
81 }
82
83 return object_type;
84 }
85
86 static void
fo_area_table_continuation_class_init(FoAreaTableContinuationClass * klass)87 fo_area_table_continuation_class_init (FoAreaTableContinuationClass *klass)
88 {
89 GObjectClass *object_class = G_OBJECT_CLASS (klass);
90
91 parent_class = g_type_class_peek_parent (klass);
92
93 object_class->finalize = fo_area_table_continuation_finalize;
94
95 FO_AREA_CLASS (klass)->debug_dump_properties = fo_area_table_continuation_debug_dump_properties;
96 FO_AREA_CLASS (klass)->size_request = fo_area_table_continuation_size_request;
97 FO_AREA_CLASS (klass)->split_before_height = fo_area_table_continuation_split_before_height;
98 FO_AREA_CLASS (klass)->split_before_height_check = fo_area_table_continuation_split_before_height_check;
99 FO_AREA_CLASS (klass)->update_after_clone =
100 fo_area_table_continuation_update_after_clone;
101 }
102
103 static void
fo_area_table_continuation_finalize(GObject * object)104 fo_area_table_continuation_finalize (GObject *object)
105 {
106 FoAreaTableContinuation *fo_area_table_continuation;
107
108 fo_area_table_continuation = FO_AREA_TABLE_CONTINUATION (object);
109
110 G_OBJECT_CLASS (parent_class)->finalize (object);
111 }
112
113
114 /**
115 * fo_area_table_continuation_new:
116 *
117 * Creates a new #FoAreaTableContinuation initialized to default value.
118 *
119 * Return value: the new #FoAreaTableContinuation
120 **/
121 FoArea*
fo_area_table_continuation_new(void)122 fo_area_table_continuation_new (void)
123 {
124 return FO_AREA (g_object_new (fo_area_table_continuation_get_type (), NULL));
125 }
126
127
128 /**
129 * fo_area_table_continuation_debug_dump_properties:
130 * @area: The #FoArea object
131 * @depth: Indent level to add to the output
132 *
133 * Logs the value of each significant property of @area then calls
134 * debug_dump_properties method of parent class.
135 **/
136 void
fo_area_table_continuation_debug_dump_properties(FoArea * area,gint depth)137 fo_area_table_continuation_debug_dump_properties (FoArea *area,
138 gint depth)
139 {
140 FoAreaTableContinuation *table_continuation;
141 gchar *indent = g_strnfill (depth * 2, ' ');
142 gchar *fo_sprintf;
143
144 g_return_if_fail (area != NULL);
145 g_return_if_fail (FO_IS_AREA_TABLE_CONTINUATION (area));
146
147 table_continuation = FO_AREA_TABLE_CONTINUATION (area);
148
149 fo_sprintf = fo_object_debug_sprintf (table_continuation->table);
150 g_log (G_LOG_DOMAIN,
151 G_LOG_LEVEL_DEBUG,
152 "%stable: %s",
153 indent,
154 fo_sprintf);
155 g_free (fo_sprintf);
156
157 fo_sprintf = fo_object_debug_sprintf (table_continuation->table_header);
158 g_log (G_LOG_DOMAIN,
159 G_LOG_LEVEL_DEBUG,
160 "%stable-header: %s",
161 indent,
162 fo_sprintf);
163 g_free (fo_sprintf);
164
165 g_free (indent);
166 FO_AREA_CLASS (parent_class)->debug_dump_properties (area, depth + 1);
167 }
168
169 /**
170 * fo_area_table_continuation_size_adjust:
171 * @area: #FoArea node to be placed within parent
172 * @data: Not used
173 *
174 * Place @area within its parent and adjust the parent's next-x and
175 * next-y properties accordingly.
176 **/
177 void
fo_area_table_continuation_size_adjust(FoArea * area,gpointer data G_GNUC_UNUSED)178 fo_area_table_continuation_size_adjust (FoArea *area,
179 gpointer data G_GNUC_UNUSED)
180 {
181 FoArea *table_continuation;
182
183 g_return_if_fail (FO_IS_AREA (area));
184 g_return_if_fail (FO_IS_AREA_TABLE_CONTINUATION (fo_area_parent (area)));
185
186 table_continuation = fo_area_parent (area);
187
188 fo_area_area_set_x (area,
189 fo_area_get_next_x (table_continuation) +
190 fo_area_area_get_start_indent (area));
191 fo_area_area_set_y (area,
192 fo_area_get_next_y (table_continuation) -
193 fo_area_area_get_space_before (area));
194 fo_area_set_next_x (table_continuation,
195 fo_area_area_get_border_before (table_continuation) +
196 fo_area_area_get_padding_before (table_continuation));
197 fo_area_set_next_y (table_continuation,
198 fo_area_get_next_y (table_continuation) -
199 fo_area_area_get_height (area));
200 fo_area_set_available_height (area,
201 fo_area_area_get_height (area));
202 fo_area_set_available_width (area,
203 fo_area_get_child_available_ipdim (table_continuation));
204 }
205
206 /**
207 * fo_area_table_continuation_set_or_split:
208 * @area: #FoArea to be either placed within the parent area or split
209 * into two areas
210 * @data: Not used
211 *
212 *
213 **/
214 void
fo_area_table_continuation_set_or_split(FoArea * area,gpointer data G_GNUC_UNUSED)215 fo_area_table_continuation_set_or_split (FoArea *area,
216 gpointer data G_GNUC_UNUSED)
217 {
218 FoArea *table_continuation;
219 gdouble table_continuation_child_available_bpdim;
220
221 g_return_if_fail (FO_IS_AREA (area));
222 g_return_if_fail (FO_IS_AREA_TABLE_CONTINUATION (fo_area_parent (area)));
223
224 table_continuation = fo_area_parent (area);
225 table_continuation_child_available_bpdim = fo_area_get_child_available_bpdim (table_continuation);
226
227 if ((table_continuation_child_available_bpdim -
228 (fo_area_get_next_y (table_continuation) -
229 fo_area_area_get_height (area))) >= 0)
230 {
231 fo_area_area_set_x (area,
232 fo_area_get_next_x (table_continuation) +
233 fo_area_area_get_start_indent (area));
234 fo_area_area_set_y (area,
235 fo_area_get_next_y (table_continuation));
236 fo_area_set_next_x (table_continuation,
237 fo_area_area_get_border_before (table_continuation) +
238 fo_area_area_get_padding_before (table_continuation));
239 fo_area_set_next_y (table_continuation,
240 fo_area_get_next_y (table_continuation) -
241 fo_area_area_get_height (area));
242 fo_area_set_available_height (area,
243 fo_area_area_get_height (area));
244 fo_area_set_available_width (area,
245 fo_area_get_child_available_ipdim (table_continuation));
246 }
247 else
248 {
249 #if defined(LIBFO_DEBUG) && 1
250 g_message ("table_continuation_set_or_split:: splitting:: child: %s; generated by: %s",
251 fo_object_debug_sprintf (area) ,
252 fo_object_debug_sprintf (area->generated_by));
253 #endif
254 area = fo_area_split_before_height (area,
255 table_continuation_child_available_bpdim -
256 fo_area_area_get_height (table_continuation));
257 table_continuation = fo_area_parent (area);
258 table_continuation_child_available_bpdim =
259 fo_area_get_child_available_bpdim (table_continuation);
260 }
261 }
262
263 /**
264 * fo_area_table_continuation_size_request:
265 * @child: Child area
266 *
267 * Check that the parent area of @child has sufficient space for
268 * @child. If not enough space, request that the parent has
269 * sufficient space allocated for it, then adjust @child and its
270 * siblings as necessary to fit into the resized parent area.
271 *
272 * Return value: Pointer to the last area generated from @child after
273 * any reallocation and resizing
274 **/
275 FoArea*
fo_area_table_continuation_size_request(FoArea * child)276 fo_area_table_continuation_size_request (FoArea *child)
277 {
278 FoArea *table_continuation;
279 FoArea *return_child;
280 FoArea *child_original_next_part;
281 FoDatatype *fo_continuation_bpdim;
282 gdouble table_continuation_child_available_bpdim;
283 gdouble table_continuation_use_height = 0.0;
284 gdouble table_continuation_target_height = 0.0;
285 gdouble child_height;
286 gdouble total_child_height = 0.0;
287
288 g_return_val_if_fail (child != NULL, NULL);
289 g_return_val_if_fail (FO_IS_AREA_AREA (child), NULL);
290 g_return_val_if_fail (!FO_AREA_IS_ROOT (child), NULL);
291 g_return_val_if_fail (fo_area_parent (child) != NULL, NULL);
292 g_return_val_if_fail (FO_IS_AREA_TABLE_CONTINUATION (fo_area_parent (child)), NULL);
293
294 child_original_next_part = child->next_part;
295
296 child_height = fo_area_area_get_height (child);
297
298 table_continuation = fo_area_parent (child);
299 table_continuation_child_available_bpdim =
300 fo_area_get_child_available_bpdim (table_continuation);
301
302 gdouble table_continuation_header_height = 0.0;
303 if ((FO_AREA_TABLE_CONTINUATION (table_continuation)->table != NULL) &&
304 (FO_AREA_TABLE_CONTINUATION (table_continuation)->table_header != NULL))
305 {
306 table_continuation_header_height =
307 fo_area_area_get_height (FO_AREA_TABLE_CONTINUATION (table_continuation)->table_header);
308 }
309
310 #if 0
311 g_message ("table_continuation_size_request:: header_height: %g",
312 table_continuation_header_height);
313 #endif
314
315 fo_area_children_foreach (table_continuation,
316 G_TRAVERSE_ALL,
317 &fo_area_accumulate_height,
318 &total_child_height);
319
320 table_continuation_target_height =
321 table_continuation_header_height +
322 total_child_height +
323 fo_area_area_get_border_before (table_continuation) +
324 fo_area_area_get_padding_before (table_continuation) +
325 fo_area_area_get_padding_after (table_continuation) +
326 fo_area_area_get_border_after (table_continuation);
327
328 fo_continuation_bpdim =
329 fo_property_get_value (fo_table_get_block_progression_dimension (table_continuation->generated_by));
330
331 if (FO_IS_LENGTH_RANGE (fo_continuation_bpdim))
332 {
333 FoDatatype *min_datatype = fo_length_range_get_minimum (fo_continuation_bpdim);
334 FoDatatype *opt_datatype = fo_length_range_get_optimum (fo_continuation_bpdim);
335 FoDatatype *max_datatype = fo_length_range_get_maximum (fo_continuation_bpdim);
336
337 if (FO_IS_LENGTH (min_datatype) &&
338 table_continuation_target_height <= fo_length_get_value (min_datatype))
339 {
340 table_continuation_use_height = fo_length_get_value (min_datatype);
341
342 #if defined(LIBFO_DEBUG) && 0
343 g_message ("table_continuation_size_request:: target: %g; min: %g",
344 table_continuation_target_height,
345 fo_length_get_value (min_datatype));
346 #endif
347 }
348 else if (FO_IS_LENGTH (opt_datatype) &&
349 table_continuation_target_height < fo_length_get_value (opt_datatype))
350 {
351 table_continuation_use_height = fo_length_get_value (opt_datatype);
352
353 #if defined(LIBFO_DEBUG) && 0
354 g_message ("table_continuation_size_request:: target: %g; opt: %g",
355 table_continuation_target_height,
356 fo_length_get_value (opt_datatype));
357 #endif
358 }
359 else if (FO_IS_LENGTH (max_datatype) &&
360 fo_length_get_value (max_datatype) < table_continuation_target_height)
361 {
362 table_continuation_use_height = fo_length_get_value (max_datatype);
363
364 #if defined(LIBFO_DEBUG) && 0
365 g_message ("table_continuation_size_request:: target: %g; max: %g",
366 table_continuation_target_height,
367 fo_length_get_value (max_datatype));
368 #endif
369 }
370 else
371 {
372 table_continuation_use_height = table_continuation_target_height;
373 }
374 }
375 else
376 {
377 g_assert_not_reached ();
378 }
379
380 if (table_continuation_child_available_bpdim < table_continuation_use_height)
381 {
382 fo_area_area_set_height (table_continuation, table_continuation_use_height);
383 table_continuation = fo_area_size_request (table_continuation);
384 /*
385 table_continuation_child_available_ipdim =
386 MAX (fo_area_get_available_width (table_continuation) -
387 fo_area_area_get_border_start (table_continuation) -
388 fo_area_area_get_padding_start (table_continuation) -
389 fo_area_area_get_padding_end (table_continuation) -
390 fo_area_area_get_border_end (table_continuation),
391 0);
392 fo_area_set_child_available_ipdim (table_continuation,
393 table_continuation_child_available_ipdim);
394 */
395 table_continuation_child_available_bpdim =
396 MAX (fo_area_get_available_height (table_continuation) -
397 table_continuation_header_height +
398 fo_area_area_get_border_before (table_continuation) -
399 fo_area_area_get_padding_before (table_continuation) -
400 fo_area_area_get_padding_after (table_continuation) -
401 fo_area_area_get_border_after (table_continuation),
402 0);
403 fo_area_set_child_available_bpdim (table_continuation,
404 table_continuation_child_available_bpdim);
405 }
406
407 total_child_height = 0;
408 fo_area_children_foreach (table_continuation,
409 G_TRAVERSE_ALL,
410 &fo_area_accumulate_height,
411 &total_child_height);
412
413 table_continuation_target_height =
414 table_continuation_header_height +
415 total_child_height +
416 fo_area_area_get_border_before (table_continuation) +
417 fo_area_area_get_padding_before (table_continuation) +
418 fo_area_area_get_padding_after (table_continuation) +
419 fo_area_area_get_border_after (table_continuation);
420
421 fo_area_set_next_x (table_continuation,
422 fo_area_area_get_border_start (table_continuation) +
423 fo_area_area_get_padding_start (table_continuation));
424 fo_area_set_next_y (table_continuation,
425 table_continuation_header_height +
426 - (fo_area_area_get_border_before (table_continuation) +
427 fo_area_area_get_padding_before (table_continuation)));
428
429 if (table_continuation_target_height <= table_continuation_child_available_bpdim)
430 {
431 fo_area_children_foreach (table_continuation,
432 G_TRAVERSE_ALL,
433 &fo_area_table_continuation_size_adjust,
434 NULL);
435
436 return_child = child;
437
438 while ((return_child->next_part != NULL) &&
439 (return_child->next_part != child_original_next_part))
440 {
441 return_child = return_child->next_part;
442 }
443
444 return return_child;
445 }
446 else
447 {
448 fo_area_children_foreach (table_continuation,
449 G_TRAVERSE_ALL,
450 &fo_area_table_continuation_set_or_split,
451 NULL);
452 #if defined(LIBFO_DEBUG) && 0
453 g_message ("table_continuation_size_request (%p):: total > available:: return:: table_continuation->last: %s; generated by: %s",
454 child,
455 fo_object_debug_sprintf (fo_area_last_child (table_continuation)),
456 fo_object_debug_sprintf (fo_area_last_child (table_continuation)->generated_by));
457 #endif
458 return_child = child;
459
460 while ((return_child->next_part != NULL) &&
461 (return_child->next_part != child_original_next_part))
462 {
463 return_child = return_child->next_part;
464 }
465
466 return return_child;
467 /*
468 return fo_area_last_child (table_continuation);
469 */
470 }
471 }
472
473 /* return the new area containing what comes after the split */
474 /* leave @area as area remaining after split */
475 FoArea*
fo_area_table_continuation_split_before_height(FoArea * area,gdouble max_height)476 fo_area_table_continuation_split_before_height (FoArea *area,
477 gdouble max_height)
478 {
479 FoArea *use_child_area;
480 gdouble minus_child_y = 0.0;
481 gdouble child_height = 0.0;
482
483 g_return_val_if_fail (FO_IS_AREA_TABLE_CONTINUATION (area), NULL);
484 g_return_val_if_fail (fo_area_n_children (area) > 0, NULL);
485 g_return_val_if_fail (max_height > 0, NULL);
486
487 /* if the current area is less than max height, then no new area */
488 if (fo_area_area_get_height (area) < max_height)
489 return NULL;
490
491 use_child_area = fo_area_first_child (area);
492
493 while (use_child_area)
494 {
495 minus_child_y = -fo_area_area_get_y (use_child_area);
496 child_height = fo_area_area_get_height (use_child_area);
497
498 if (minus_child_y + child_height >= max_height)
499 break;
500 else
501 use_child_area = fo_area_next_sibling (use_child_area);
502 }
503
504 #if defined(LIBFO_DEBUG) && 1
505 g_message ("table_continuation_split_before_height:: splitting: area: %s; generated by: %s; y: %f; height: %f",
506 fo_object_debug_sprintf (use_child_area),
507 fo_object_debug_sprintf (fo_area_get_generated_by (use_child_area)),
508 fo_area_area_get_y (use_child_area),
509 fo_area_area_get_height (use_child_area));
510 #endif
511
512 if (use_child_area == NULL)
513 return NULL;
514
515 if (minus_child_y >= max_height)
516 {
517 /* max_height falls before use_child_area, i.e. in space between areas */
518
519 if (use_child_area == fo_area_first_child (area))
520 {
521 return NULL;
522 }
523 else
524 {
525 FoFo *child_fo =
526 fo_area_get_generated_by (use_child_area);
527 FoDatatype *child_kwpwp_datatype =
528 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
529 FoDatatype *child_kwpwc_datatype =
530 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
531
532 FoFo *prev_child_fo =
533 fo_area_get_generated_by (fo_area_prev_sibling (use_child_area));
534 FoDatatype *prev_child_kwnwp_datatype =
535 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
536 FoDatatype *prev_child_kwnwc_datatype =
537 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
538
539 /* FIXME: Need to handle integer keeps */
540 if ((FO_IS_ENUM (prev_child_kwnwp_datatype) &&
541 fo_enum_get_value (prev_child_kwnwp_datatype) == FO_ENUM_ENUM_AUTO) &&
542 (FO_IS_ENUM (prev_child_kwnwc_datatype) &&
543 fo_enum_get_value (prev_child_kwnwc_datatype) == FO_ENUM_ENUM_AUTO) &&
544 (FO_IS_ENUM (child_kwpwp_datatype) &&
545 fo_enum_get_value (child_kwpwp_datatype) == FO_ENUM_ENUM_AUTO) &&
546 (FO_IS_ENUM (child_kwpwc_datatype) &&
547 fo_enum_get_value (child_kwpwc_datatype) == FO_ENUM_ENUM_AUTO))
548 {
549 /* If got to here, all relevant keeps are 'auto' */
550 FoArea *clone = fo_area_clone (area);
551
552 fo_area_unlink_with_next_siblings (use_child_area);
553 fo_area_insert_with_next_siblings (clone, 0, use_child_area);
554
555 return clone;
556 }
557 else
558 {
559 gdouble minus_prev_y =
560 fo_area_area_get_y (fo_area_prev_sibling (use_child_area));
561 gdouble prev_height =
562 fo_area_area_get_height (fo_area_prev_sibling (use_child_area));
563 /* If can't split between use_child_area and previous, maybe
564 can split at lower height */
565 return fo_area_table_continuation_split_before_height (area,
566 minus_prev_y +
567 prev_height);
568 }
569 }
570 }
571 else
572 {
573 /* max_height falls within use_child_area */
574 gboolean child_can_split = fo_area_split_before_height_check (use_child_area,
575 max_height -
576 minus_child_y);
577
578 if (child_can_split)
579 {
580 FoArea *clone = fo_area_clone (area);
581 FoArea *split_child = fo_area_split_before_height (use_child_area,
582 max_height -
583 minus_child_y);
584 fo_area_unlink_with_next_siblings (split_child);
585 fo_area_insert_with_next_siblings (clone, 0, split_child);
586
587 return clone;
588 }
589 else
590 {
591 /* If can't split use_child_area, maybe
592 can split at lower height */
593 return fo_area_table_continuation_split_before_height (area,
594 minus_child_y);
595 }
596 }
597 }
598
599 /* return the new area containing what comes after the split */
600 /* leave @area as area remaining after split */
601 gboolean
fo_area_table_continuation_split_before_height_check(FoArea * area,gdouble max_height)602 fo_area_table_continuation_split_before_height_check (FoArea *area,
603 gdouble max_height)
604 {
605 FoArea *use_child_area;
606 gdouble minus_child_y = 0.0;
607 gdouble child_height = 0.0;
608
609 g_return_val_if_fail (FO_IS_AREA_TABLE_CONTINUATION (area), FALSE);
610 g_return_val_if_fail (fo_area_n_children (area) > 0, FALSE);
611 g_return_val_if_fail (max_height > 0, FALSE);
612
613 /* if the current area is less than max height, then no new area */
614 if (fo_area_area_get_height (area) < max_height)
615 return FALSE;
616
617 use_child_area = fo_area_first_child (area);
618
619 while (use_child_area)
620 {
621 minus_child_y = -fo_area_area_get_y (use_child_area);
622 child_height = fo_area_area_get_height (use_child_area);
623
624 if (minus_child_y + child_height >= max_height)
625 break;
626 else
627 use_child_area = fo_area_next_sibling (use_child_area);
628 }
629
630 #if defined(LIBFO_DEBUG) && 1
631 g_message ("table_continuation_split_before_height_check:: splitting: area: %s; generated by: %s; y: %f; height: %f",
632 fo_object_debug_sprintf (use_child_area),
633 fo_object_debug_sprintf (fo_area_get_generated_by (use_child_area)),
634 fo_area_area_get_y (use_child_area),
635 fo_area_area_get_height (use_child_area));
636 #endif
637
638 if (use_child_area == NULL)
639 return FALSE;
640
641 if (minus_child_y >= max_height)
642 {
643 /* max_height falls before use_child_area, i.e. in space between areas */
644
645 if (use_child_area == fo_area_first_child (area))
646 {
647 return FALSE;
648 }
649 else
650 {
651 FoFo *child_fo =
652 fo_area_get_generated_by (use_child_area);
653 FoDatatype *child_kwpwp_datatype =
654 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
655 FoDatatype *child_kwpwc_datatype =
656 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_previous (child_fo)));
657
658 FoFo *prev_child_fo =
659 fo_area_get_generated_by (fo_area_prev_sibling (use_child_area));
660 FoDatatype *prev_child_kwnwp_datatype =
661 fo_keep_get_within_page (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
662 FoDatatype *prev_child_kwnwc_datatype =
663 fo_keep_get_within_column (fo_property_get_value (fo_block_fo_get_keep_with_next (prev_child_fo)));
664
665 /* FIXME: Need to handle integer keeps */
666 if ((FO_IS_ENUM (prev_child_kwnwp_datatype) &&
667 fo_enum_get_value (prev_child_kwnwp_datatype) == FO_ENUM_ENUM_AUTO) &&
668 (FO_IS_ENUM (prev_child_kwnwc_datatype) &&
669 fo_enum_get_value (prev_child_kwnwc_datatype) == FO_ENUM_ENUM_AUTO) &&
670 (FO_IS_ENUM (child_kwpwp_datatype) &&
671 fo_enum_get_value (child_kwpwp_datatype) == FO_ENUM_ENUM_AUTO) &&
672 (FO_IS_ENUM (child_kwpwc_datatype) &&
673 fo_enum_get_value (child_kwpwc_datatype) == FO_ENUM_ENUM_AUTO))
674 {
675 /* If got to here, all relevant keeps are 'auto' */
676 return TRUE;
677 }
678 else
679 {
680 gdouble minus_prev_y =
681 fo_area_area_get_y (fo_area_prev_sibling (use_child_area));
682 gdouble prev_height =
683 fo_area_area_get_height (fo_area_prev_sibling (use_child_area));
684 /* If can't split between use_child_area and previous, maybe
685 can split at lower height */
686 return fo_area_table_continuation_split_before_height_check (area,
687 minus_prev_y +
688 prev_height);
689 }
690 }
691 }
692 else
693 {
694 /* max_height falls within use_child_area */
695 gboolean child_can_split = fo_area_split_before_height_check (use_child_area,
696 max_height -
697 minus_child_y);
698
699 if (child_can_split)
700 {
701 return TRUE;
702 }
703 else
704 {
705 /* If can't split use_child_area, maybe
706 can split at lower height */
707 return fo_area_table_continuation_split_before_height_check (area,
708 minus_child_y);
709 }
710 }
711 }
712
713 /**
714 * fo_area_table_continuation_update_after_clone:
715 * @clone: New object cloned from @original
716 * @original: Original area object
717 *
718 * Update the FoAreaTableContinuation-specific instance variables of @clone to
719 * match those of @original
720 **/
721 void
fo_area_table_continuation_update_after_clone(FoArea * clone,FoArea * original)722 fo_area_table_continuation_update_after_clone (FoArea *clone,
723 FoArea *original)
724 {
725 FoAreaTableContinuation *table_continuation;
726
727 g_return_if_fail (clone != NULL);
728 g_return_if_fail (FO_IS_AREA_TABLE_CONTINUATION (clone));
729 g_return_if_fail (original != NULL);
730 g_return_if_fail (FO_IS_AREA_TABLE_CONTINUATION (original) ||
731 FO_IS_AREA_TABLE (original));
732
733 table_continuation = FO_AREA_TABLE_CONTINUATION (clone);
734
735 FO_AREA_CLASS (parent_class)->update_after_clone (clone, original);
736
737 if (FO_IS_AREA_TABLE (original))
738 {
739 FoArea *child = NULL;
740
741 table_continuation->table = original;
742
743 child = fo_area_first_child (original);
744
745 while (child && G_TYPE_FROM_INSTANCE (child) != FO_TYPE_AREA_TABLE_HEADER)
746 {
747 child = fo_area_next_sibling (child);
748 }
749
750 table_continuation->table_header = child;
751 }
752 else
753 {
754 table_continuation->table =
755 FO_AREA_TABLE_CONTINUATION (original)->table;
756 table_continuation->table_header =
757 FO_AREA_TABLE_CONTINUATION (original)->table_header;
758 }
759
760 }
761