1
4
5# include "luametatex.h"
6
7
45
46
52
53
67
68
69
70typedef enum saved_box_entries {
71 saved_box_slot_entry = 0,
72 saved_box_context_entry = 0,
73 saved_box_packing_entry = 0,
74 saved_box_amount_entry = 1,
75 saved_box_direction_entry = 1,
76 saved_box_dir_pointer_entry = 1,
77 saved_box_attr_list_entry = 2,
78 saved_box_pack_entry = 2,
79 saved_box_orientation_entry = 2,
80 saved_box_anchor_entry = 3,
81 saved_box_geometry_entry = 3,
82 saved_box_xoffset_entry = 3,
83 saved_box_yoffset_entry = 4,
84 saved_box_xmove_entry = 4,
85 saved_box_ymove_entry = 4,
86 saved_box_shift_entry = 5,
87 saved_box_source_entry = 5,
88 saved_box_target_entry = 5,
89 saved_box_class_entry = 6,
90 saved_box_state_entry = 6,
91 saved_box_axis_entry = 6,
92 saved_box_retain_entry = 7,
93 saved_box_callback_entry = 7,
94 saved_box_option_entry = 7,
95 saved_box_n_of_records = 8,
96} saved_box_entries;
97
98typedef enum saved_box_options {
99 saved_box_reverse_option = 0x01,
100 saved_box_container_option = 0x02,
101 saved_box_limit_option = 0x04,
102} saved_box_options;
103
104inline static void saved_box_initialize(void)
105{
106 saved_type(0) = saved_record_0;
107 saved_type(1) = saved_record_1;
108 saved_type(2) = saved_record_2;
109 saved_type(3) = saved_record_3;
110 saved_type(4) = saved_record_4;
111 saved_type(5) = saved_record_5;
112 saved_type(6) = saved_record_6;
113 saved_type(7) = saved_record_7;
114 saved_record(0) = box_save_type;
115 saved_record(1) = box_save_type;
116 saved_record(2) = box_save_type;
117 saved_record(3) = box_save_type;
118 saved_record(4) = box_save_type;
119 saved_record(5) = box_save_type;
120 saved_record(6) = box_save_type;
121 saved_record(7) = box_save_type;
122}
123
124# define saved_box_slot saved_value_1(saved_box_slot_entry)
125# define saved_box_context saved_value_2(saved_box_context_entry)
126# define saved_box_packing saved_value_3(saved_box_packing_entry)
127# define saved_box_amount saved_value_1(saved_box_amount_entry)
128# define saved_box_direction saved_value_2(saved_box_direction_entry)
129# define saved_box_dir_pointer saved_value_3(saved_box_dir_pointer_entry)
130# define saved_box_attr_list saved_value_1(saved_box_attr_list_entry)
131# define saved_box_pack saved_value_2(saved_box_pack_entry)
132# define saved_box_orientation saved_value_3(saved_box_orientation_entry)
133# define saved_box_anchor saved_value_1(saved_box_anchor_entry)
134# define saved_box_geometry saved_value_2(saved_box_geometry_entry)
135# define saved_box_xoffset saved_value_3(saved_box_xoffset_entry)
136# define saved_box_yoffset saved_value_1(saved_box_yoffset_entry)
137# define saved_box_xmove saved_value_2(saved_box_xmove_entry)
138# define saved_box_ymove saved_value_3(saved_box_ymove_entry)
139# define saved_box_shift saved_value_1(saved_box_shift_entry)
140# define saved_box_source saved_value_2(saved_box_source_entry)
141# define saved_box_target saved_value_3(saved_box_target_entry)
142# define saved_box_class saved_value_1(saved_box_class_entry)
143# define saved_box_state saved_value_2(saved_box_state_entry)
144# define saved_box_axis saved_value_3(saved_box_axis_entry)
145# define saved_box_retain saved_value_1(saved_box_retain_entry)
146# define saved_box_callback saved_value_2(saved_box_callback_entry)
147# define saved_box_option saved_value_3(saved_box_option_entry)
148
149void tex_show_packaging_group(const char *package)
150{
151 tex_print_str_esc(package);
152 tex_print_str(saved_box_packing == packing_exactly ? " to " : " spread ");
153 tex_print_dimension(saved_box_amount, pt_unit);
154}
155
156int tex_show_packaging_record(void)
157{
158 tex_print_str("box, ");
159 switch (saved_type(0)) {
160 case saved_record_0:
161 tex_print_format("slot %i, context %i, packing %i", save_value_1(0), saved_value_2(0), saved_value_3(0));
162 break;
163 case saved_record_1:
164 tex_print_format("amount %p, direction %i, pointer %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
165 break;
166 case saved_record_2:
167 tex_print_format("attrlist %i, pack %i, orientation %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
168 break;
169 case saved_record_3:
170 tex_print_format("anchor %i, geometry %i, xoffset %p", saved_value_1(0), saved_value_2(0), saved_value_3(0));
171 break;
172 case saved_record_4:
173 tex_print_format("yoffset %p, xmove %p, ymove %p", saved_value_1(0), saved_value_2(0), saved_value_3(0));
174 break;
175 case saved_record_5:
176 tex_print_format("shift %p, source %i, target %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
177 break;
178 case saved_record_6:
179 tex_print_format("class %i, state %i, axis %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
180 break;
181 case saved_record_7:
182 tex_print_format("retain %i, callback %i, option %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
183 break;
184 default:
185 return 0;
186 }
187 return 1;
188}
189
190int tex_get_packaging_context(void) { return saved_box_context; }
191int tex_get_packaging_shift (void) { return saved_box_shift; }
192
193static void tex_aux_scan_full_spec(halfword context, quarterword c, quarterword spec_direction, int just_pack, scaled shift, halfword slot, halfword callback)
194{
195 quarterword spec_packing = packing_additional;
196 int spec_amount = 0;
197 halfword attrlist = null;
198 halfword orientation = 0;
199 scaled xoffset = 0;
200 scaled yoffset = 0;
201 scaled xmove = 0;
202 scaled ymove = 0;
203 halfword source = 0;
204 halfword target = 0;
205 halfword anchor = 0;
206 halfword geometry = 0;
207 halfword axis = 0;
208 halfword state = 0;
209 halfword retain = 0;
210 halfword mainclass = unset_noad_class;
211 halfword options = 0;
212 int brace = 0;
213 while (1) {
214
215 switch (tex_scan_character("tascdoxyrlTASCDOXYRL", 1, 1, 1)) {
216 case 0:
217 goto DONE;
218 case 't': case 'T':
219 switch (tex_scan_character("aoAO", 0, 0, 0)) {
220 case 'a': case 'A':
221 if (tex_scan_mandate_keyword("target", 2)) {
222 target = tex_scan_integer(1, NULL);
223 }
224 break;
225 case 'o': case 'O':
226 spec_packing = packing_exactly;
227 spec_amount = tex_scan_dimension(0, 0, 0, 0, NULL);
228 break;
229 default:
230 tex_aux_show_keyword_error("target|to");
231 goto DONE;
232 }
233 break;
234 case 'a': case 'A':
235 switch (tex_scan_character("dntxDNTX", 0, 0, 0)) {
236 case 'd': case 'D':
237 if (tex_scan_mandate_keyword("adapt", 2)) {
238 spec_packing = packing_adapted;
239 spec_amount = tex_scan_limited_scale(0);
240 }
241 break;
242 case 't': case 'T':
243 if (tex_scan_mandate_keyword("attr", 2)) {
244 attrlist = tex_scan_attribute(attrlist);
245 }
246 break;
247 case 'n': case 'N':
248 if (tex_scan_mandate_keyword("anchor", 2)) {
249 switch (tex_scan_character("sS", 0, 0, 0)) {
250 case 's': case 'S':
251 anchor = tex_scan_anchors(0);
252 break;
253 default:
254 anchor = tex_scan_anchor(0);
255 break;
256 }
257 }
258 break;
259 case 'x': case 'X':
260 if (tex_scan_mandate_keyword("axis", 2)) {
261 axis |= tex_scan_box_axis();
262 }
263 break;
264 default:
265 tex_aux_show_keyword_error("adapt|attr|anchor|axis");
266 goto DONE;
267 }
268 break;
269 case 's': case 'S':
270 switch (tex_scan_character("hpoHPO", 0, 0, 0)) {
271 case 'h': case 'H':
272
277 if (tex_scan_mandate_keyword("shift", 2)) {
278 shift = tex_scan_dimension(0, 0, 0, 0, NULL);
279 }
280 break;
281 case 'p': case 'P':
282 if (tex_scan_mandate_keyword("spread", 2)) {
283 spec_packing = packing_additional;
284 spec_amount = tex_scan_dimension(0, 0, 0, 0, NULL);
285 }
286 break;
287 case 'o': case 'O':
288 if (tex_scan_mandate_keyword("source", 2)) {
289 source = tex_scan_integer(1, NULL);
290 }
291 break;
292 default:
293 tex_aux_show_keyword_error("shift|spread|source");
294 goto DONE;
295 }
296 break;
297 case 'd': case 'D':
298 switch (tex_scan_character("eiEI", 0, 0, 0)) {
299 case 'i': case 'I':
300
305# if (0)
306 if (tex_scan_mandate_keyword("direction", 2)) {
307 spec_direction = tex_scan_direction(0);
308 }
309# else
310 if (tex_scan_keyword("rection")) {
311 spec_direction = tex_scan_direction(0);
312 } else if (tex_scan_character("rR", 0, 0, 0)) {
313
314 if (tex_scan_character("tT", 0, 1, 0)) {
315 switch (tex_scan_character("lLrR", 0, 0, 0)) {
316 case 'l': case 'L':
317 spec_direction = 0;
318 break;
319 case 'r': case 'R':
320 spec_direction = 1;
321 break;
322 default:
323 goto BADDIR;
324 }
325 if (! tex_scan_character("tT", 0, 0, 0)) {
326 goto BADDIR;
327 }
328 } else {
329 BADDIR:
330 tex_aux_show_keyword_error("tlt|trt");
331 goto DONE;
332 }
333 } else {
334 tex_aux_show_keyword_error("direction|dir");
335 goto DONE;
336 }
337# endif
338 break;
339 case 'e': case 'E':
340 if (tex_scan_mandate_keyword("delay", 2)) {
341 state |= package_u_leader_delayed;
342 }
343 break;
344 default:
345 tex_aux_show_keyword_error("direction|delay");
346 goto DONE;
347 }
348 break;
349 case 'o': case 'O':
350 if (tex_scan_mandate_keyword("orientation", 1)) {
351 orientation = tex_scan_orientation(0);
352 }
353 break;
354 case 'x': case 'X':
355 switch (tex_scan_character("omOM", 0, 0, 0)) {
356 case 'o': case 'O' :
357 if (tex_scan_mandate_keyword("xoffset", 2)) {
358 xoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
359 }
360 break;
361 case 'm': case 'M' :
362 if (tex_scan_mandate_keyword("xmove", 2)) {
363 xmove = tex_scan_dimension(0, 0, 0, 0, NULL);
364 }
365 break;
366 default:
367 tex_aux_show_keyword_error("xoffset|xmove");
368 goto DONE;
369 }
370 break;
371 case 'y': case 'Y':
372 switch (tex_scan_character("omOM", 0, 0, 0)) {
373 case 'o': case 'O' :
374 if (tex_scan_mandate_keyword("yoffset", 2)) {
375 yoffset = tex_scan_dimension(0, 0, 0, 0, NULL);
376 }
377 break;
378 case 'm': case 'M' :
379 if (tex_scan_mandate_keyword("ymove", 2)) {
380 ymove = tex_scan_dimension(0, 0, 0, 0, NULL);
381 }
382 break;
383 default:
384 tex_aux_show_keyword_error("yoffset|ymove");
385 goto DONE;
386 }
387 break;
388 case 'r': case 'R':
389 if (tex_scan_character("eE", 0, 0, 0)) {
390 switch (tex_scan_character("vVtT", 0, 0, 0)) {
391 case 'v': case 'V' :
392 if (tex_scan_mandate_keyword("reverse", 3)) {
393 options |= saved_box_reverse_option;
394 }
395 break;
396 case 't': case 'T' :
397 if (tex_scan_mandate_keyword("retain", 3)) {
398 retain = tex_scan_integer(0, NULL);
399 }
400 break;
401 default:
402 tex_aux_show_keyword_error("reverse|retain");
403 goto DONE;
404 }
405 }
406 break;
407 case 'c': case 'C':
408 switch (tex_scan_character("olOL", 0, 0, 0)) {
409 case 'o': case 'O' :
410 if (tex_scan_mandate_keyword("container", 2)) {
411 options |= saved_box_container_option;
412 }
413 break;
414 case 'l': case 'L' :
415 if (tex_scan_mandate_keyword("class", 2)) {
416 mainclass = tex_scan_math_class_number(0);
417 }
418 break;
419 default:
420 tex_aux_show_keyword_error("container|class");
421 goto DONE;
422 }
423 break;
424 case 'l': case 'L':
425 if (tex_scan_mandate_keyword("limit", 1)) {
426 options |= saved_box_limit_option;
427 }
428 break;
429 case '{':
430 brace = 1;
431 goto DONE;
432 default:
433 goto DONE;
434 }
435 }
436 DONE:
437 if (anchor || source || target) {
438 geometry |= anchor_geometry;
439 }
440 if (orientation || xmove || ymove) {
441 geometry |= orientation_geometry;
442 }
443 if (xoffset || yoffset) {
444 geometry |= offset_geometry;
445 }
446
451 if (! attrlist) {
452
453 attrlist = tex_current_attribute_list();
454 }
455
456 add_attribute_reference(attrlist);
457
458 saved_box_initialize();
459 saved_box_slot = slot;
460 saved_box_context = context;
461
462 saved_box_packing = spec_packing;
463 saved_box_amount = spec_amount;
464
465 saved_box_direction = spec_direction;
466 if (spec_direction != direction_unknown) {
467 saved_box_dir_pointer = lmt_dir_state.text_dir_ptr;
468 lmt_dir_state.text_dir_ptr = tex_new_dir(normal_dir_subtype, spec_direction);
469 } else {
470 saved_box_dir_pointer = null;
471 }
472 saved_box_attr_list = attrlist;
473 saved_box_pack = just_pack;
474 saved_box_orientation = orientation;
475 saved_box_anchor = anchor;
476 saved_box_geometry = geometry;
477 saved_box_xoffset = xoffset;
478 saved_box_yoffset = yoffset;
479 saved_box_xmove = xmove;
480 saved_box_ymove = ymove;
481 saved_box_source = source;
482 saved_box_target = target;
483 saved_box_state = state;
484 saved_box_option = options;
485 saved_box_shift = shift;
486 saved_box_axis = axis;
487 saved_box_class = mainclass;
488 saved_box_retain = retain;
489 saved_box_callback = callback;
490 lmt_save_state.save_stack_data.ptr += saved_box_n_of_records;
491 tex_new_save_level(c);
492 if (! brace) {
493 tex_scan_left_brace();
494 }
495 update_tex_par_direction(spec_direction);
496 update_tex_text_direction(spec_direction);
497}
498
499
516
517packaging_state_info lmt_packaging_state = {
518 .total_stretch = { 0 },
519 .total_shrink = { 0 },
520 .last_badness = 0,
521 .last_overshoot = 0,
522 .post_adjust_tail = null,
523 .pre_adjust_tail = null,
524 .post_migrate_tail = null,
525 .pre_migrate_tail = null,
526 .last_leftmost_char = null,
527 .last_rightmost_char = null,
528 .pack_begin_line = 0,
529
530 .best_height_plus_depth = 0,
531 .previous_char_ptr = null,
532 .font_expansion_ratio = 0,
533 .padding = 0,
534 .page_discards_tail = null,
535 .page_discards_head = null,
536 .split_discards_head = null,
537};
538
539
575
576scaled tex_char_stretch(halfword p)
577{
578 if (! tex_has_glyph_option(p, glyph_option_no_expansion)) {
579 halfword f = glyph_font(p);
580 halfword m = font_max_stretch(f);
581 if (m > 0) {
582 halfword c = glyph_character(p);
583 scaled e = tex_char_ef_from_font(f, c);
584 if (e > 0) {
585 scaled dw = tex_calculated_glyph_width(p, m) - tex_char_width_from_glyph(p);
586 if (dw > 0) {
587 return tex_round_xn_over_d(dw, e, scaling_factor);
588 }
589 }
590 }
591 }
592 return 0;
593}
594
595scaled tex_char_shrink(halfword p)
596{
597 if (! tex_has_glyph_option(p, glyph_option_no_expansion)) {
598 halfword f = glyph_font(p);
599 halfword m = font_max_shrink(f);
600 if (m > 0) {
601 halfword c = glyph_character(p);
602 scaled e = tex_char_cf_from_font(f, c);
603 if (e > 0) {
604 scaled dw = tex_char_width_from_glyph(p) - tex_calculated_glyph_width(p, -m);
605 if (dw > 0) {
606 return tex_round_xn_over_d(dw, e, scaling_factor);
607 }
608 }
609 }
610 }
611 return 0;
612}
613
614scaled tex_kern_stretch(halfword p)
615{
616 scaled w = kern_amount(p);
617 if (w) {
618 halfword l = lmt_packaging_state.previous_char_ptr;
619 if (l && node_type(l) == glyph_node && ! tex_has_glyph_option(l, glyph_option_no_expansion)) {
620 scaled m = font_max_stretch(glyph_font(l));
621 if (m > 0) {
622 scaled e = tex_char_ef_from_font(glyph_font(l), glyph_character(l));
623 if (e > 0) {
624 scaled dw = w - tex_round_xn_over_d(w, scaling_factor + m, scaling_factor);
625 if (dw > 0) {
626 return tex_round_xn_over_d(dw, e, scaling_factor);
627 }
628 }
629 }
630 }
631 }
632 return 0;
633}
634
635scaled tex_kern_shrink(halfword p)
636{
637 scaled w = kern_amount(p) ;
638 if (w) {
639 halfword l = lmt_packaging_state.previous_char_ptr;
640 if (l && node_type(l) == glyph_node && ! tex_has_glyph_option(l, glyph_option_no_expansion)) {
641 halfword m = font_max_shrink(glyph_font(l));
642 if (m > 0) {
643 scaled e = tex_char_cf_from_font(glyph_font(l), glyph_character(l));
644 if (e > 0) {
645 scaled dw = tex_round_xn_over_d(w, scaling_factor - m, scaling_factor) - w;
646 if (dw > 0) {
647 return tex_round_xn_over_d(dw, e, scaling_factor);
648 }
649 }
650 }
651 }
652 }
653 return 0;
654}
655
656static void tex_aux_set_kern_expansion(halfword p, halfword ex_ratio)
657{
658 scaled w = kern_amount(p) ;
659 if (w ) {
660 halfword l = lmt_packaging_state.previous_char_ptr;
661 if (l && node_type(l) == glyph_node && ! tex_has_glyph_option(l, glyph_option_no_expansion)) {
662 halfword f = glyph_font(l);
663 halfword c = glyph_character(l);
664 if (ex_ratio > 0) {
665 scaled e = tex_char_ef_from_font(f, c);
666 if (e > 0) {
667 halfword m = font_max_stretch(f);
668 if (m > 0) {
669 e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared);
670 kern_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor;
671 }
672 }
673 } else if (ex_ratio < 0) {
674 scaled e = tex_char_cf_from_font(f, c);
675 if (e > 0) {
676 halfword m = font_max_shrink(f);
677 if (m > 0) {
678 e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared);
679 kern_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor;
680 }
681 }
682 }
683 }
684 }
685}
686
687static void tex_aux_set_glyph_expansion(halfword p, int ex_ratio)
688{
689 switch (node_type(p)) {
690 case glyph_node:
691 if (! tex_has_glyph_option(p, glyph_option_no_expansion)) {
692 if (ex_ratio > 0) {
693 halfword f = glyph_font(p);
694 halfword c = glyph_character(p);
695 scaled e = tex_char_ef_from_font(f, c);
696 if (e > 0) {
697 halfword m = font_max_stretch(f);
698 if (m > 0) {
699 e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared);
700 glyph_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor;
701 }
702 }
703 } else if (ex_ratio < 0) {
704 halfword f = glyph_font(p);
705 halfword c = glyph_character(p);
706 scaled e = tex_char_cf_from_font(f, c);
707 if (e > 0) {
708 halfword m = font_max_shrink(f);
709 if (m > 0) {
710 e = tex_ext_xn_over_d(ex_ratio * e, m, scaling_factor_squared);
711 glyph_expansion(p) = tex_fix_expand_value(f, e) * scaling_factor;
712 }
713 }
714 }
715 }
716 break;
717 case disc_node:
718 {
719 halfword r = disc_pre_break_head(p);
720 while (r) {
721 if (node_type(r) == glyph_node) {
722 tex_aux_set_glyph_expansion(r, ex_ratio);
723 }
724 r = node_next(r);
725 }
726 r = disc_post_break_head(p);
727 while (r) {
728 if (node_type(r) == glyph_node) {
729 tex_aux_set_glyph_expansion(r, ex_ratio);
730 }
731 r = node_next(r);
732 }
733 r = disc_no_break_head(p);
734 while (r) {
735 if (node_type(r) == glyph_node) {
736 tex_aux_set_glyph_expansion(r, ex_ratio);
737 }
738 r = node_next(r);
739 }
740 break;
741 }
742 default:
743 tex_normal_error("font expansion", "invalid node type");
744 break;
745 }
746}
747
748scaled tex_left_marginkern(halfword p)
749{
750 while (p && node_type(p) == glue_node) {
751 p = node_next(p);
752 }
753 if (p && node_type(p) == kern_node && node_subtype(p) == left_margin_kern_subtype) {
754 return kern_amount(p);
755 } else {
756 return 0;
757 }
758}
759
760scaled tex_right_marginkern(halfword p)
761{
762 if (p) {
763 p = tex_tail_of_node_list(p);
764
768 while (p) {
769 switch(node_type(p)) {
770 case glue_node:
771
772 p = node_prev(p);
773 break;
774 case kern_node:
775 if (node_subtype(p) == right_margin_kern_subtype) {
776 return kern_amount(p);
777 } else {
778 return 0;
779 }
780 case disc_node:
781
786 p = node_prev(p);
787 if (p && node_type(p) == kern_node && node_subtype(p) == right_margin_kern_subtype) {
788 return kern_amount(p);
789 } else {
790 return 0;
791 }
792 default:
793 return 0;
794 }
795 }
796 }
797 return 0;
798}
799
800
806
807scaled tex_char_protrusion(halfword p, int side)
808{
809 if (side == left_margin_kern_subtype) {
810 lmt_packaging_state.last_leftmost_char = null;
811 } else {
812 lmt_packaging_state.last_rightmost_char = null;
813 }
814 if (! p || node_type(p) != glyph_node || tex_has_glyph_option(p, glyph_option_no_protrusion)) {
815 return 0;
816 } else if (side == left_margin_kern_subtype) {
817 lmt_packaging_state.last_leftmost_char = p;
818 return tex_char_left_protrusion_from_glyph(p);
819 } else {
820 lmt_packaging_state.last_rightmost_char = p;
821 return tex_char_right_protrusion_from_glyph(p);
822 }
823}
824
825
831
832int tex_ignore_math_skip(halfword p)
833{
834 if (math_skip_mode_par == math_skip_only_when_skip) {
835 if (node_subtype(p) == end_inline_math) {
836 if (tex_math_skip_boundary(node_next(p))) {
837 return 0;
838 }
839 } else {
840 if (tex_math_skip_boundary(node_prev(p))) {
841 return 0;
842 }
843 }
844 } else if (math_skip_mode_par == math_skip_only_when_no_skip) {
845 if (node_subtype(p) == end_inline_math) {
846 if (! tex_math_skip_boundary(node_next(p))) {
847 return 0;
848 }
849 } else {
850 if (! tex_math_skip_boundary(node_prev(p))) {
851 return 0;
852 }
853 }
854 } else {
855 return 0;
856 }
857 tex_reset_math_glue_to_zero(p);
858 return 1;
859}
860
861# define fix_int(val,min,max) (val < min ? min : (val > max ? max : val))
862
863inline static halfword tex_aux_used_order(halfword *total)
864{
865 if (total[filll_glue_order]) {
866 return filll_glue_order;
867 } else if (total[fill_glue_order]) {
868 return fill_glue_order;
869 } else if (total[fil_glue_order]) {
870 return fil_glue_order;
871 } else if (total[fi_glue_order]) {
872 return fi_glue_order;
873 } else {
874 return normal_glue_order;
875 }
876}
877
878
902
903
907
908inline static void tex_aux_promote_pre_migrated(halfword r, halfword p)
909{
910 halfword pa = box_pre_adjusted(p);
911 halfword pm = box_pre_migrated(p);
912 if (pa) {
913 if (lmt_packaging_state.pre_adjust_tail) {
914 lmt_packaging_state.pre_adjust_tail = tex_append_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, pa, "promote");
915 } else if (box_pre_adjusted(r)) {
916 tex_couple_nodes(box_pre_adjusted(r), pa);
917 } else {
918 box_pre_adjusted(r) = pa;
919 }
920 box_pre_adjusted(p) = null;
921 }
922 if (pm) {
923 if (lmt_packaging_state.pre_migrate_tail) {
924 tex_couple_nodes(lmt_packaging_state.pre_migrate_tail, pm);
925 lmt_packaging_state.pre_migrate_tail = tex_tail_of_node_list(pm);
926 } else {
927
928 halfword rm = box_pre_migrated(r);
929 if (rm) {
930 tex_couple_nodes(pm, rm);
931 }
932 box_pre_migrated(r) = pm;
933 }
934 box_pre_migrated(p) = null;
935 }
936}
937
938inline static void tex_aux_promote_post_migrated(halfword r, halfword p)
939{
940 halfword pa = box_post_adjusted(p);
941 halfword pm = box_post_migrated(p);
942 if (pa) {
943 if (lmt_packaging_state.post_adjust_tail) {
944 lmt_packaging_state.post_adjust_tail = tex_append_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, pa, "promote");
945 } else if (box_post_adjusted(r)) {
946 tex_couple_nodes(box_post_adjusted(r), pa);
947 } else {
948 box_post_adjusted(r) = pa;
949 }
950 box_post_adjusted(p) = null;
951 }
952 if (pm) {
953 if (lmt_packaging_state.post_migrate_tail) {
954 tex_couple_nodes(lmt_packaging_state.post_migrate_tail, pm);
955 lmt_packaging_state.post_migrate_tail = tex_tail_of_node_list(pm);
956 } else {
957
958 halfword rm = box_post_migrated(r);
959 if (rm) {
960 tex_couple_nodes(tex_tail_of_node_list(rm), pm);
961 } else {
962 box_post_migrated(r) = pm;
963 }
964 }
965 box_post_migrated(p) = null;
966 }
967}
968
969inline static halfword tex_aux_post_migrate(halfword r, halfword p)
970{
971 halfword n = p;
972 halfword nn = node_next(p);
973 halfword pm = box_post_migrated(r);
974 if (p == box_list(r)) {
975 box_list(r) = nn;
976 if (nn) {
977 node_prev(nn) = null;
978 }
979 } else {
980 tex_couple_nodes(node_prev(p), nn);
981 }
982 if (pm) {
983 tex_couple_nodes(tex_tail_of_node_list(pm), n);
984 } else {
985 box_post_migrated(r) = n;
986 }
987 node_next(n) = null;
988 p = nn;
989 return p;
990}
991
992inline static halfword tex_aux_normal_migrate(halfword r, halfword p)
993{
994 halfword n = p;
995 halfword nn = node_next(p);
996 if (p == box_list(r)) {
997 box_list(r) = nn;
998 if (nn) {
999 node_prev(nn) = null;
1000 }
1001 } else {
1002 tex_couple_nodes(node_prev(p), nn);
1003 }
1004 tex_couple_nodes(lmt_packaging_state.post_migrate_tail, n);
1005 lmt_packaging_state.post_migrate_tail = n;
1006 node_next(n) = null;
1007 p = nn;
1008 return p;
1009}
1010
1011static void tex_aux_append_diagnostic_rule(halfword box, halfword rule)
1012{
1013 halfword n = box_list(box);
1014 if (n) {
1015 halfword t = tex_tail_of_node_list(n);
1016 halfword c = t;
1017 while (c && node_type(c) == glue_node) {
1018 switch (node_subtype(c)) {
1019 case par_fill_right_skip_glue:
1020 case par_init_right_skip_glue:
1021 case right_skip_glue:
1022 case right_hang_skip_glue:
1023 c = node_prev(c);
1024 break;
1025 default:
1026 goto DONE;
1027 }
1028 }
1029 DONE:
1030 if (c) {
1031 n = node_next(c);
1032 if (n) {
1033 tex_couple_nodes(rule, n);
1034 }
1035 } else {
1036 c = t;
1037 }
1038 tex_couple_nodes(c, rule);
1039 } else {
1040 box_list(box) = rule;
1041 }
1042}
1043
1044void tex_repack(halfword p, scaled w, int m)
1045{
1046 if (p) {
1047 halfword tmp;
1048 switch (node_type(p)) {
1049 case hlist_node:
1050 tmp = tex_hpack(box_list(p), w, m, box_dir(p), holding_none_option, box_limit_none);
1051 break;
1052 case vlist_node:
1053 tmp = tex_vpack(box_list(p), w, m > packing_additional ? packing_additional : m, max_dimension, box_dir(p), holding_none_option, NULL);
1054 break;
1055 default:
1056 return;
1057 }
1058 box_width(p) = box_width(tmp);
1059 box_height(p) = box_height(tmp);
1060 box_depth(p) = box_depth(tmp);
1061 box_glue_set(p) = box_glue_set(tmp);
1062 box_glue_order(p) = box_glue_order(tmp);
1063 box_glue_sign(p) = box_glue_sign(tmp);
1064 box_list(tmp) = null;
1065 tex_flush_node(tmp);
1066 }
1067}
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1083
1084void tex_freeze(halfword p, int recurse, int limitate, halfword factor)
1085{
1086 if (p) {
1087 switch (node_type(p)) {
1088 case hlist_node:
1089 {
1090 halfword c = box_list(p);
1091 double set = (double) box_glue_set(p);
1092 halfword order = box_glue_order(p);
1093 halfword sign = box_glue_sign(p);
1094 if (factor > 0) {
1095 set *= factor * 0.001;
1096 } else if (factor < 0) {
1097 double max = - factor * 0.001;
1098 if (set > max) {
1099 set = max;
1100 }
1101 }
1102 while (c) {
1103 switch (node_type(c)) {
1104 case glue_node:
1105 switch (sign) {
1106 case stretching_glue_sign:
1107 if (glue_stretch_order(c) == order) {
1108 glue_amount(c) += limitate == hlist_node ? glue_stretch(c) : scaledround(glue_stretch(c) * set);
1109 }
1110 break;
1111 case shrinking_glue_sign:
1112 if (glue_shrink_order(c) == order) {
1113 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1114 }
1115 break;
1116 }
1117 glue_stretch(c) = 0;
1118 glue_shrink(c) = 0;
1119 glue_stretch_order(c) = 0;
1120 glue_shrink_order(c) = 0;
1121 break;
1122 case hlist_node:
1123 case vlist_node:
1124 if (recurse) {
1125 tex_freeze(c, recurse, limitate, factor);
1126 }
1127 break;
1128 case math_node:
1129 switch (sign) {
1130 case stretching_glue_sign:
1131 if (math_stretch_order(c) == order) {
1132 math_amount(c) += limitate == hlist_node ? math_stretch(c) : scaledround(math_stretch(c) * set);
1133 }
1134 break;
1135 case shrinking_glue_sign:
1136 if (math_shrink_order(c) == order) {
1137 math_amount(c) += scaledround(math_shrink(c) * set);
1138 }
1139 break;
1140 }
1141 math_stretch(c) = 0;
1142 math_shrink(c) = 0;
1143 math_stretch_order(c) = 0;
1144 math_shrink_order(c) = 0;
1145 break;
1146 default:
1147 break;
1148 }
1149 c = node_next(c);
1150 }
1151 box_glue_set(p) = 0;
1152 box_glue_order(p) = 0;
1153 box_glue_sign(p) = 0;
1154 }
1155 break;
1156 case vlist_node:
1157 {
1158 halfword c = box_list(p);
1159 double set = (double) box_glue_set(p);
1160 halfword order = box_glue_order(p);
1161 halfword sign = box_glue_sign(p);
1162 if (factor > 0) {
1163 set *= factor * 0.001;
1164 } else if (factor < 0) {
1165 double max = - factor * 0.001;
1166 if (set > max) {
1167 set = max;
1168 }
1169 }
1170 while (c) {
1171
1172 switch (node_type(c)) {
1173 case glue_node:
1174 switch (sign) {
1175 case stretching_glue_sign:
1176 if (glue_stretch_order(c) == order) {
1177
1178 glue_amount(c) += limitate == vlist_node ? glue_stretch(c) : scaledround(glue_stretch(c) * set);
1179 }
1180 break;
1181 case shrinking_glue_sign:
1182 if (glue_shrink_order(c) == order) {
1183
1184 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1185 }
1186 break;
1187 }
1188 glue_stretch(c) = 0;
1189 glue_shrink(c) = 0;
1190 glue_stretch_order(c) = 0;
1191 glue_shrink_order(c) = 0;
1192 break;
1193 case hlist_node:
1194 case vlist_node:
1195 if (recurse) {
1196 tex_freeze(c, recurse, limitate, factor);
1197 }
1198 break;
1199 default:
1200 break;
1201 }
1202 c = node_next(c);
1203 }
1204 box_glue_set(p) = 0;
1205 box_glue_order(p) = 0;
1206 box_glue_sign(p) = 0;
1207 }
1208 break;
1209 default:
1210 return;
1211 }
1212 }
1213}
1214
1215void tex_limit(halfword p)
1216{
1217
1221 if (p) {
1222 halfword c = box_list(p);
1223 double set = (double) box_glue_set(p);
1224 halfword order = box_glue_order(p);
1225 halfword sign = box_glue_sign(p);
1226 int limit = set > 1 && order == normal_glue_order;
1227 if (limit) {
1228 double nonfrozen = 0;
1229 double frozen = 0;
1230 while (c) {
1231 if (node_type(c) == glue_node) {
1232 switch (sign) {
1233 case stretching_glue_sign:
1234 if (glue_stretch_order(c) == order) {
1235 if (tex_has_glue_option(c, glue_option_limit)) {
1236 frozen += glue_stretch(c);
1237 } else {
1238 nonfrozen += glue_stretch(c);
1239 }
1240 }
1241 break;
1242 case shrinking_glue_sign:
1243 if (glue_shrink_order(c) == order) {
1244 if (tex_has_glue_option(c, glue_option_limit)) {
1245 frozen -= glue_shrink(c);
1246 } else {
1247 nonfrozen -= glue_shrink(c);
1248 }
1249 }
1250 break;
1251 }
1252 }
1253 c = node_next(c);
1254 }
1255 if (frozen) {
1256 set = (set * (frozen + nonfrozen) - frozen) / nonfrozen;
1257 } else {
1258 limit = 0;
1259 }
1260 }
1261 c = box_list(p);
1262 while (c) {
1263 if (node_type(c) == glue_node) {
1264 switch (sign) {
1265 case stretching_glue_sign:
1266 if (glue_stretch_order(c) == order) {
1267 if (limit && tex_has_glue_option(c, glue_option_limit)) {
1268 glue_amount(c) += glue_stretch(c);
1269 } else {
1270 glue_amount(c) += scaledround(glue_stretch(c) * set);
1271 }
1272 }
1273 break;
1274 case shrinking_glue_sign:
1275 if (glue_shrink_order(c) == order) {
1276 if (limit && tex_has_glue_option(c, glue_option_limit)) {
1277 glue_amount(c) -= glue_shrink(c);
1278 } else {
1279 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1280 }
1281 }
1282 break;
1283 }
1284 glue_stretch(c) = 0;
1285 glue_shrink(c) = 0;
1286 glue_stretch_order(c) = 0;
1287 glue_shrink_order(c) = 0;
1288 }
1289 c = node_next(c);
1290 }
1291 box_glue_set(p) = 0;
1292 box_glue_order(p) = 0;
1293 box_glue_sign(p) = 0;
1294 }
1295}
1296
1297scaled tex_stretch(halfword p)
1298{
1299 scaled stretch = 0;
1300 if (p) {
1301 switch (node_type(p)) {
1302 case hlist_node:
1303 case vlist_node:
1304 if (box_glue_sign(p) == stretching_glue_sign) {
1305 halfword c = box_list(p);
1306 halfword order = box_glue_order(p);
1307 while (c) {
1308 switch (node_type(c)) {
1309 case glue_node:
1310 if (glue_stretch_order(c) == order) {
1311 stretch += glue_stretch(c);
1312 }
1313 break;
1314 case math_node:
1315 if (math_stretch_order(c) == order) {
1316 stretch += math_stretch(c);
1317 }
1318 break;
1319 }
1320 c = node_next(c);
1321 }
1322 }
1323 break;
1324 }
1325 }
1326 return stretch;
1327}
1328
1329scaled tex_shrink(halfword p)
1330{
1331 scaled shrink = 0;
1332 if (p) {
1333 switch (node_type(p)) {
1334 case hlist_node:
1335 case vlist_node:
1336 if (box_glue_sign(p) == shrinking_glue_sign) {
1337 halfword c = box_list(p);
1338 halfword order = box_glue_order(p);
1339 while (c) {
1340 switch (node_type(c)) {
1341 case glue_node:
1342 if (glue_shrink_order(c) == order) {
1343 shrink += glue_shrink(c);
1344 }
1345 break;
1346 case math_node:
1347 if (math_shrink_order(c) == order) {
1348 shrink += math_shrink(c);
1349 }
1350 break;
1351 }
1352 c = node_next(c);
1353 }
1354 }
1355 break;
1356 }
1357 }
1358 return shrink;
1359}
1360
1361halfword tex_hpack(halfword p, scaled w, int m, singleword pack_direction, int retain, int limit)
1362{
1363
1364 halfword q = null;
1365
1366 scaled h = 0;
1367
1368 scaled d = 0;
1369
1370 scaled x = 0;
1371
1372 singleword hpack_dir = pack_direction == direction_unknown ?(singleword) text_direction_par : pack_direction;
1373 int disc_level = 0;
1374 int has_uleader = 0;
1375 halfword pack_interrupt[8];
1376 scaled font_stretch = 0;
1377 scaled font_shrink = 0;
1378 int adjust_spacing = adjust_spacing_off;
1379 int has_limit = box_limit_mode_hlist ? 1 : (limit == box_limit_line && box_limit_mode_line ? 1 : -1);
1380
1381 halfword r = tex_new_node(hlist_node, unknown_list);
1382 box_dir(r) = hpack_dir;
1383 lmt_packaging_state.last_badness = 0;
1384 lmt_packaging_state.last_overshoot = 0;
1385 switch(m) {
1386 case packing_linebreak:
1387 m = packing_expanded;
1388
1389 case packing_substitute:
1390 adjust_spacing = tex_checked_font_adjust(
1391 lmt_linebreak_state.adjust_spacing,
1392 lmt_linebreak_state.adjust_spacing_step,
1393 lmt_linebreak_state.adjust_spacing_shrink,
1394 lmt_linebreak_state.adjust_spacing_stretch
1395 );
1396 break;
1397 default:
1398 adjust_spacing = tex_checked_font_adjust(
1399 adjust_spacing_par,
1400 adjust_spacing_step_par,
1401 adjust_spacing_shrink_par,
1402 adjust_spacing_stretch_par
1403 );
1404 break;
1405 }
1406 box_list(r) = p;
1407 switch (m) {
1408 case packing_expanded:
1409
1410 lmt_packaging_state.previous_char_ptr = null;
1411 break;
1412 case packing_adapted:
1413 if (w > scaling_factor) {
1414 w = scaling_factor;
1415 } else if (w < -scaling_factor) {
1416 w = -scaling_factor;
1417 }
1418 }
1419 for (int i = normal_glue_order; i <= filll_glue_order; i++) {
1420 lmt_packaging_state.total_stretch[i] = 0;
1421 lmt_packaging_state.total_shrink[i] = 0;
1422 }
1423
1436 while (p) {
1437 switch (node_type(p)) {
1438 case glyph_node:
1439 {
1440 scaledwhd whd;
1441 if (adjust_spacing) {
1442 switch (m) {
1443 case packing_expanded:
1444 {
1445 lmt_packaging_state.previous_char_ptr = p;
1446 font_stretch += tex_char_stretch(p);
1447 font_shrink += tex_char_shrink(p);
1448 break;
1449 }
1450 case packing_substitute:
1451 lmt_packaging_state.previous_char_ptr = p;
1452 if (lmt_packaging_state.font_expansion_ratio != 0) {
1453 tex_aux_set_glyph_expansion(p, lmt_packaging_state.font_expansion_ratio);
1454 }
1455 break;
1456 }
1457 }
1458 whd = tex_glyph_dimensions_ex(p);
1459 x += whd.wd;
1460 if (whd.ht > h) {
1461 h = whd.ht;
1462 }
1463 if (whd.dp > d) {
1464 d = whd.dp;
1465 }
1466 break;
1467 }
1468 case hlist_node:
1469 case vlist_node:
1470 {
1471
1477 halfword s = box_shift_amount(p);
1478 scaledwhd whd = tex_pack_dimensions(p);
1479 x += whd.wd;
1480 if (whd.ht - s > h) {
1481 h = whd.ht - s;
1482 }
1483 if (whd.dp + s > d) {
1484 d = whd.dp + s;
1485 }
1486 tex_aux_promote_pre_migrated(r, p);
1487 tex_aux_promote_post_migrated(r, p);
1488 break;
1489 }
1490 case unset_node:
1491 x += box_width(p);
1492 if (box_height(p) > h) {
1493 h = box_height(p);
1494 }
1495 if (box_depth(p) > d) {
1496 d = box_depth(p);
1497 }
1498
1499
1500 break;
1501 case rule_node:
1502
1509 x += rule_width(p);
1510 if (rule_height(p) > h) {
1511 h = rule_height(p);
1512 }
1513 if (rule_depth(p) > d) {
1514 d = rule_depth(p);
1515 }
1516 break;
1517 case glue_node:
1518
1519 {
1520 switch (m) {
1521 case packing_adapted:
1522 if (w < 0) {
1523 if (glue_shrink_order(p) == normal_glue_order) {
1524 glue_amount(p) -= scaledround(-0.001 * w * (double) glue_shrink(p));
1525 }
1526 } else if (w > 0) {
1527 if (glue_stretch_order(p) == normal_glue_order) {
1528 glue_amount(p) += scaledround( 0.001 * w * (double) glue_stretch(p));
1529 }
1530 }
1531 x += glue_amount(p);
1532 glue_shrink_order(p) = normal_glue_order;
1533 glue_shrink(p) = 0;
1534 glue_stretch_order(p) = normal_glue_order;
1535 glue_stretch(p) = 0;
1536 break;
1537 default:
1538 {
1539 halfword o;
1540 x += glue_amount(p);
1541 o = glue_stretch_order(p);
1542 lmt_packaging_state.total_stretch[o] += glue_stretch(p);
1543 o = glue_shrink_order(p);
1544 lmt_packaging_state.total_shrink[o] += glue_shrink(p);
1545 }
1546 }
1547 if (is_leader(p)) {
1548 halfword gl = glue_leader_ptr(p);
1549 scaled ht = 0;
1550 scaled dp = 0;
1551 switch (node_type(gl)) {
1552 case hlist_node:
1553 case vlist_node:
1554 ht = box_height(gl);
1555 dp = box_depth(gl);
1556 break;
1557 case rule_node:
1558 ht = rule_height(gl);
1559 dp = rule_depth(gl);
1560 break;
1561 }
1562 if (ht > h) {
1563 h = ht;
1564 }
1565 if (dp > d) {
1566 d = dp;
1567 }
1568 if (node_subtype(p) == u_leaders) {
1569 has_uleader = 1;
1570 }
1571 }
1572 if (! has_limit && tex_has_glue_option(p, glue_option_limit)) {
1573 has_limit = 1;
1574 }
1575 break;
1576 }
1577 case kern_node:
1578 if (adjust_spacing == adjust_spacing_full && node_subtype(p) == font_kern_subtype) {
1579 switch (m) {
1580 case packing_expanded:
1581 {
1582 font_stretch += tex_kern_stretch(p);
1583 font_shrink += tex_kern_shrink(p);
1584 break;
1585 }
1586 case packing_substitute:
1587 if (lmt_packaging_state.font_expansion_ratio != 0) {
1588 tex_aux_set_kern_expansion(p, lmt_packaging_state.font_expansion_ratio);
1589 }
1590 break;
1591 }
1592 }
1593 x += tex_kern_dimension_ex(p);
1594 break;
1595 case disc_node:
1596 if (adjust_spacing) {
1597 switch (m) {
1598 case packing_expanded:
1599
1603 break;
1604 case packing_substitute:
1605 if (lmt_packaging_state.font_expansion_ratio != 0) {
1606 tex_aux_set_glyph_expansion(p, lmt_packaging_state.font_expansion_ratio);
1607 }
1608 break;
1609 }
1610 }
1611 if (disc_no_break_head(p)) {
1612 pack_interrupt[disc_level] = node_next(p);
1613 ++disc_level;
1614 p = disc_no_break(p);
1615 }
1616 break;
1617 case math_node:
1618 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
1619 x += math_surround(p);
1620 } else {
1621 halfword o;
1622 x += math_amount(p);
1623 o = math_stretch_order(p);
1624 lmt_packaging_state.total_stretch[o] += math_stretch(p);
1625 o = math_shrink_order(p);
1626 lmt_packaging_state.total_shrink[o] += math_shrink(p);
1627 }
1628 break;
1629 case dir_node:
1630 break;
1631 case insert_node:
1632 if (retain_inserts(retain)) {
1633 break;
1634 } else if (lmt_packaging_state.post_migrate_tail) {
1635 p = tex_aux_normal_migrate(r, p);
1636
1637 continue;
1638 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_insert)) {
1639 halfword l = insert_list(p);
1640 p = tex_aux_post_migrate(r, p);
1641 while (l) {
1642 l = node_type(l) == insert_node ? tex_aux_post_migrate(r, l) : node_next(l);
1643 }
1644
1645 continue;
1646 } else {
1647
1648 break;
1649 }
1650 case mark_node:
1651 if (retain_marks(retain)) {
1652 break;
1653 } else if (lmt_packaging_state.post_migrate_tail) {
1654 p = tex_aux_normal_migrate(r, p);
1655
1656 continue;
1657 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_mark)) {
1658 p = tex_aux_post_migrate(r, p);
1659
1660 continue;
1661 } else {
1662
1663 break;
1664 }
1665 case adjust_node:
1666
1670 if (adjust_list(p) && ! retain_adjusts(retain)) {
1671 halfword next = node_next(p);
1672 halfword current = p;
1673
1674 if (p == box_list(r)) {
1675 box_list(r) = next;
1676 if (next) {
1677 node_prev(next) = null;
1678 }
1679 } else {
1680 tex_couple_nodes(node_prev(p), next);
1681 }
1682 if (lmt_packaging_state.post_adjust_tail || lmt_packaging_state.pre_adjust_tail) {
1683 tex_adjust_passon(r, current);
1684 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_adjust)) {
1685 tex_adjust_attach(r, current);
1686 }
1687 p = next;
1688 continue;
1689 } else {
1690 break;
1691 }
1692 default:
1693 break;
1694 }
1695
1700 if (disc_level > 0) {
1701 p = node_next(p);
1702 if (! p) {
1703 --disc_level;
1704 p = pack_interrupt[disc_level];
1705 }
1706 } else {
1707 q = p;
1708 p = node_next(p);
1709 }
1710 }
1711 box_height(r) = h;
1712 box_depth(r) = d;
1713
1718 switch (m) {
1719 case packing_additional:
1720 w += x;
1721 break;
1722 case packing_adapted:
1723 w = x;
1724 break;
1725 }
1726 box_width(r) = w;
1727 x = w - x;
1728
1729 if (x == 0) {
1730 box_glue_sign(r) = normal_glue_sign;
1731 box_glue_order(r) = normal_glue_order;
1732 box_glue_set(r) = 0.0;
1733 goto EXIT;
1734 } else if (x > 0) {
1735
1740 halfword o = tex_aux_used_order(lmt_packaging_state.total_stretch);
1741 if ((m == packing_expanded) && (o == normal_glue_order) && (font_stretch > 0)) {
1742 lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_stretch, scaling_factor_double);
1743 goto EXIT;
1744 }
1745 box_glue_order(r) = o;
1746 box_glue_sign(r) = stretching_glue_sign;
1747 if (lmt_packaging_state.total_stretch[o]) {
1748 box_glue_set(r) = (glueratio) ((double) x / lmt_packaging_state.total_stretch[o]);
1749 } else {
1750
1751 box_glue_sign(r) = normal_glue_sign;
1752 box_glue_set(r) = 0.0;
1753 }
1754 if (o == normal_glue_order && box_list(r)) {
1755
1758 lmt_packaging_state.last_badness = tex_badness(x, lmt_packaging_state.total_stretch[normal_glue_order]);
1759 if (lmt_packaging_state.last_badness > hbadness_par) {
1760 int callback_id = lmt_callback_defined(hpack_quality_callback);
1761 if (callback_id > 0) {
1762 if (q) {
1763 halfword rule = null;
1764 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1765 lmt_packaging_state.last_badness > 100 ? "underfull" : "loose",
1766 lmt_packaging_state.last_badness,
1767 r,
1768 abs(lmt_packaging_state.pack_begin_line),
1769 lmt_input_state.input_line,
1770 tex_current_input_file_name(),
1771 &rule
1772 );
1773 if (rule && rule != r) {
1774 tex_aux_append_diagnostic_rule(r, rule);
1775 }
1776 }
1777 } else {
1778 tex_print_nlp();
1779 if (lmt_packaging_state.last_badness > 100) {
1780 tex_print_format("%l[package: underfull \\hbox (badness %i)", lmt_packaging_state.last_badness);
1781 } else {
1782 tex_print_format("%l[package: loose \\hbox (badness %i)", lmt_packaging_state.last_badness);
1783 }
1784 goto COMMON_ENDING;
1785 }
1786 }
1787 }
1788 goto EXIT;
1789 } else {
1790
1793 halfword o = tex_aux_used_order(lmt_packaging_state.total_shrink);
1794 if ((m == packing_expanded) && (o == normal_glue_order) && (font_shrink > 0)) {
1795 lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(x, font_shrink, scaling_factor_double);
1796 goto EXIT;
1797 }
1798 box_glue_order(r) = o;
1799 box_glue_sign(r) = shrinking_glue_sign;
1800 if (lmt_packaging_state.total_shrink[o]) {
1801 box_glue_set(r) = (glueratio) ((double) (-x) / (double) lmt_packaging_state.total_shrink[o]);
1802 } else {
1803
1804 box_glue_sign(r) = normal_glue_sign;
1805 box_glue_set(r) = 0.0;
1806 }
1807 if (o == normal_glue_order && box_list(r)) {
1808 if (lmt_packaging_state.total_shrink[o] < -x) {
1809 int overshoot = -x - lmt_packaging_state.total_shrink[normal_glue_order];
1810 lmt_packaging_state.last_badness = scaling_factor_squared;
1811 lmt_packaging_state.last_overshoot = overshoot;
1812
1813 box_glue_set(r) = 1.0;
1814
1815 if ((overshoot > hfuzz_par) || (hbadness_par < 100)) {
1816 int callback_id = lmt_callback_defined(hpack_quality_callback);
1817 halfword rule = null;
1818 if (callback_id > 0) {
1819 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1820 "overfull",
1821 overshoot,
1822 r,
1823 abs(lmt_packaging_state.pack_begin_line),
1824 lmt_input_state.input_line,
1825 tex_current_input_file_name(),
1826 &rule);
1827 } else if (q && overfull_rule_par > 0) {
1828 rule = tex_new_rule_node(normal_rule_subtype);
1829 rule_width(rule) = overfull_rule_par;
1830 }
1831 if (rule && rule != r) {
1832 tex_aux_append_diagnostic_rule(r, rule);
1833 }
1834 if (callback_id == 0) {
1835 tex_print_nlp();
1836 tex_print_format("%l[package: overfull \\hbox (%p too wide)", overshoot);
1837 goto COMMON_ENDING;
1838 }
1839 }
1840 } else {
1841
1842 lmt_packaging_state.last_badness = tex_badness(-x, lmt_packaging_state.total_shrink[normal_glue_order]);
1843 if (lmt_packaging_state.last_badness > hbadness_par) {
1844 int callback_id = lmt_callback_defined(hpack_quality_callback);
1845 if (callback_id > 0) {
1846 halfword rule = null;
1847 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1848 "tight",
1849 lmt_packaging_state.last_badness,
1850 r,
1851 abs(lmt_packaging_state.pack_begin_line),
1852 lmt_input_state.input_line,
1853 tex_current_input_file_name(),
1854 &rule);
1855 if (rule && rule != r) {
1856 tex_aux_append_diagnostic_rule(r, rule);
1857 }
1858 } else {
1859 tex_print_nlp();
1860 tex_print_format("%l[package: tight \\hbox (badness %i)", lmt_packaging_state.last_badness);
1861 goto COMMON_ENDING;
1862 }
1863 }
1864 }
1865 }
1866 goto EXIT;
1867 }
1868 COMMON_ENDING:
1869
1870 if (lmt_page_builder_state.output_active) {
1871 tex_print_format(" has occurred while \\output is active]");
1872 } else if (lmt_packaging_state.pack_begin_line == 0) {
1873 tex_print_format(" detected at line %i]", lmt_input_state.input_line);
1874 } else if (lmt_packaging_state.pack_begin_line > 0) {
1875 tex_print_format(" in paragraph at lines %i--%i]", lmt_packaging_state.pack_begin_line, lmt_input_state.input_line);
1876 } else {
1877 tex_print_format(" in alignment at lines %i--%i]", -lmt_packaging_state.pack_begin_line, lmt_input_state.input_line);
1878 }
1879 tex_print_ln();
1880 lmt_print_state.font_in_short_display = null_font;
1881 if (tracing_full_boxes_par > 0) {
1882 halfword detail = show_node_details_par;
1883 show_node_details_par = tracing_full_boxes_par;
1884 tex_short_display(box_list(r));
1885 tex_print_ln();
1886 tex_begin_diagnostic();
1887 tex_show_box(r);
1888 tex_end_diagnostic();
1889 show_node_details_par = detail;
1890 }
1891 EXIT:
1892 if ((m == packing_expanded) && (lmt_packaging_state.font_expansion_ratio != 0)) {
1893 lmt_packaging_state.font_expansion_ratio = fix_int(lmt_packaging_state.font_expansion_ratio, -scaling_factor, scaling_factor);
1894 q = box_list(r);
1895 box_list(r) = null;
1896 tex_flush_node(r);
1897
1898 r = tex_hpack(q, w, packing_substitute, hpack_dir, holding_none_option, box_limit_none);
1899 } else {
1900 if (has_uleader) {
1901 set_box_package_state(r, package_u_leader_found);
1902 }
1903 if (has_limit > 0) {
1904 tex_limit(r);
1905 }
1906 }
1907
1908 lmt_packaging_state.font_expansion_ratio = 0;
1909 return r;
1910}
1911
1912halfword tex_filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, halfword d, int just_pack, halfword attr, int state, int retain)
1913{
1914 halfword head;
1915 singleword direction = (singleword) checked_direction_value(d);
1916
1917 if (just_pack) {
1918 head = node_next(p);
1919 } else if (node_type(p) == temp_node && ! node_next(p)) {
1920 head = node_next(p);
1921 } else {
1922
1923 head = node_next(p);
1924 if (head) {
1925 node_prev(head) = null;
1926 if (tex_list_has_glyph(head)) {
1927 tex_handle_hyphenation(head, qt);
1928 head = tex_handle_glyphrun(head, grp, direction);
1929 }
1930 if (head) {
1931
1932 head = lmt_hpack_filter_callback(head, w, m, grp, direction, attr);
1933 }
1934 }
1935 }
1936 head = tex_hpack(head, w, m, direction, retain, box_limit_none);
1937 if (has_box_package_state(head, package_u_leader_found)) {
1938 if (head && normalize_line_mode_permitted(normalize_line_mode_par, flatten_h_leaders_mode)) {
1939 if (! is_box_package_state(state, package_u_leader_delayed)) {
1940 tex_flatten_leaders(head, grp, just_pack);
1941 }
1942 }
1943 }
1944 return head;
1945}
1946
1947
1948
1949scaledwhd tex_natural_hsizes(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order)
1950{
1951 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
1952 scaled gp = 0;
1953 scaled gm = 0;
1954 while (p && p != pp) {
1955 switch (node_type(p)) {
1956 case glyph_node:
1957 {
1958 scaledwhd whd = tex_glyph_dimensions_ex(p);
1959 siz.wd += whd.wd;
1960 if (whd.ht > siz.ht) {
1961 siz.ht = whd.ht;
1962 }
1963 if (whd.dp > siz.dp) {
1964 siz.dp = whd.dp;
1965 }
1966 break;
1967 }
1968 case hlist_node:
1969 case vlist_node:
1970 {
1971 scaled s = box_shift_amount(p);
1972 scaledwhd whd = tex_pack_dimensions(p);
1973 siz.wd += whd.wd;
1974 if (whd.ht - s > siz.ht) {
1975 siz.ht = whd.ht - s;
1976 }
1977 if (whd.dp + s > siz.dp) {
1978 siz.dp = whd.dp + s;
1979 }
1980 break;
1981 }
1982 case unset_node:
1983 siz.wd += box_width(p);
1984 if (box_height(p) > siz.ht) {
1985 siz.ht = box_height(p);
1986 }
1987 if (box_depth(p) > siz.dp) {
1988 siz.dp = box_depth(p);
1989 }
1990 break;
1991 case rule_node:
1992 siz.wd += rule_width(p);
1993 if (rule_height(p) > siz.ht) {
1994 siz.ht = rule_height(p);
1995 }
1996 if (rule_depth(p) > siz.dp) {
1997 siz.dp = rule_depth(p);
1998 }
1999 break;
2000 case glue_node:
2001 siz.wd += glue_amount(p);
2002 switch (g_sign) {
2003 case stretching_glue_sign:
2004 if (glue_stretch_order(p) == g_order) {
2005 gp += glue_stretch(p);
2006 }
2007 break;
2008 case shrinking_glue_sign:
2009 if (glue_shrink_order(p) == g_order) {
2010 gm += glue_shrink(p);
2011 }
2012 break;
2013 }
2014 if (is_leader(p)) {
2015 halfword gl = glue_leader_ptr(p);
2016 halfword ht = 0;
2017 halfword dp = 0;
2018 switch (node_type(gl)) {
2019 case hlist_node:
2020 case vlist_node:
2021 ht = box_height(gl);
2022 dp = box_depth(gl);
2023 break;
2024 case rule_node:
2025 ht = rule_height(gl);
2026 dp = rule_depth(gl);
2027 break;
2028 }
2029 if (ht) {
2030 siz.ht = ht;
2031 }
2032 if (dp > siz.dp) {
2033 siz.dp = dp;
2034 }
2035 }
2036 break;
2037 case kern_node:
2038 siz.wd += tex_kern_dimension_ex(p);
2039 break;
2040 case disc_node:
2041 {
2042 scaledwhd whd = tex_natural_hsizes(disc_no_break_head(p), null, g_mult, g_sign, g_order);
2043 siz.wd += whd.wd;
2044 if (whd.ht > siz.ht) {
2045 siz.ht = whd.ht;
2046 }
2047 if (whd.dp > siz.dp) {
2048 siz.dp = whd.dp;
2049 }
2050 }
2051 break;
2052 case math_node:
2053 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2054 siz.wd += math_surround(p);
2055 } else {
2056 siz.wd += math_amount(p);
2057 switch (g_sign) {
2058 case stretching_glue_sign:
2059 if (math_stretch_order(p) == g_order) {
2060 gp += math_stretch(p);
2061 }
2062 break;
2063 case shrinking_glue_sign:
2064 if (math_shrink_order(p) == g_order) {
2065 gm += math_shrink(p);
2066 }
2067 break;
2068 }
2069 }
2070 break;
2071 case sub_box_node:
2072
2073 break;
2074 case sub_mlist_node:
2075 {
2076
2077 scaledwhd whd = tex_natural_hsizes(kernel_math_list(p), null, 0.0, 0, 0);
2078 siz.wd += whd.wd;
2079 if (whd.ht > siz.ht) {
2080 siz.ht = whd.ht;
2081 }
2082 if (whd.dp > siz.dp) {
2083 siz.dp = whd.dp;
2084 }
2085 }
2086 break;
2087 default:
2088 break;
2089 }
2090 p = node_next(p);
2091 }
2092 siz.ns = siz.wd;
2093 switch (g_sign) {
2094 case stretching_glue_sign:
2095 siz.wd += glueround((glueratio)(g_mult) * (glueratio)(gp));
2096 break;
2097 case shrinking_glue_sign:
2098 siz.wd -= glueround((glueratio)(g_mult) * (glueratio)(gm));
2099 break;
2100 }
2101 return siz;
2102}
2103
2104scaledwhd tex_natural_vsizes(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order)
2105{
2106 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
2107 scaled gp = 0;
2108 scaled gm = 0;
2109 while (p && p != pp) {
2110 switch (node_type(p)) {
2111 case hlist_node:
2112 case vlist_node:
2113 {
2114 scaled s = box_shift_amount(p);
2115 scaledwhd whd = tex_pack_dimensions(p);
2116 if (whd.wd + s > siz.wd) {
2117 siz.wd = whd.wd + s;
2118 }
2119 siz.ht += siz.dp + whd.ht;
2120 siz.dp = whd.dp;
2121 }
2122 break;
2123 case unset_node:
2124 siz.ht += siz.dp + box_height(p);
2125 siz.dp = box_depth(p);
2126 if (box_width(p) > siz.wd) {
2127 siz.wd = box_width(p);
2128 }
2129 break;
2130 case rule_node:
2131 siz.ht += siz.dp + rule_height(p);
2132 siz.dp = rule_depth(p);
2133 if (rule_width(p) > siz.wd) {
2134 siz.wd = rule_width(p);
2135 }
2136 break;
2137 case glue_node:
2138 {
2139 siz.ht += siz.dp + glue_amount(p);
2140 siz.dp = 0;
2141 if (is_leader(p)) {
2142 halfword gl = glue_leader_ptr(p);
2143 halfword wd = 0;
2144 switch (node_type(gl)) {
2145 case hlist_node:
2146 case vlist_node:
2147 wd = box_width(gl);
2148 break;
2149 case rule_node:
2150 wd = rule_width(gl);
2151 break;
2152 }
2153 if (wd > siz.wd) {
2154 siz.wd = wd;
2155 }
2156 }
2157 switch (g_sign) {
2158 case stretching_glue_sign:
2159 if (glue_stretch_order(p) == g_order) {
2160 gp += glue_stretch(p);
2161 }
2162 break;
2163 case shrinking_glue_sign:
2164 if (glue_shrink_order(p) == g_order) {
2165 gm += glue_shrink(p);
2166 }
2167 break;
2168 }
2169 break;
2170 }
2171 case kern_node:
2172 siz.ht += siz.dp + kern_amount(p);
2173 siz.dp = 0;
2174 break;
2175 case glyph_node:
2176 tex_confusion("glyph in vpack");
2177 break;
2178 case disc_node:
2179 tex_confusion("discretionary in vpack");
2180 break;
2181 default:
2182 break;
2183 }
2184 p = node_next(p);
2185 }
2186 siz.ns = siz.ht;
2187 switch (g_sign) {
2188 case stretching_glue_sign:
2189 siz.ht += glueround((glueratio)(g_mult) * (glueratio)(gp));
2190 break;
2191 case shrinking_glue_sign:
2192 siz.ht -= glueround((glueratio)(g_mult) * (glueratio)(gm));
2193 break;
2194 }
2195 return siz;
2196}
2197
2198
2199
2200halfword tex_natural_width(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order)
2201{
2202 scaled wd = 0;
2203 scaled gp = 0;
2204 scaled gm = 0;
2205 while (p && p != pp) {
2206
2207 switch (node_type(p)) {
2208 case glyph_node:
2209 wd += tex_glyph_width(p);
2210 break;
2211 case hlist_node:
2212 case vlist_node:
2213 case unset_node:
2214 wd += box_width(p);
2215 break;
2216 case rule_node:
2217 wd += rule_width(p);
2218 break;
2219 case glue_node:
2220 wd += glue_amount(p);
2221 switch (g_sign) {
2222 case stretching_glue_sign:
2223 if (glue_stretch_order(p) == g_order) {
2224 gp += glue_stretch(p);
2225 }
2226 break;
2227 case shrinking_glue_sign:
2228 if (glue_shrink_order(p) == g_order) {
2229 gm += glue_shrink(p);
2230 }
2231 break;
2232 }
2233 break;
2234 case kern_node:
2235 wd += kern_amount(p);
2236 break;
2237 case disc_node:
2238 wd += tex_natural_width(disc_no_break(p), null, g_mult, g_sign, g_order);
2239 break;
2240 case math_node:
2241 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2242 wd += math_surround(p);
2243 } else {
2244 wd += math_amount(p);
2245 switch (g_sign) {
2246 case stretching_glue_sign:
2247 if (math_stretch_order(p) == g_order) {
2248 gp += math_stretch(p);
2249 }
2250 break;
2251 case shrinking_glue_sign:
2252 if (math_shrink_order(p) == g_order) {
2253 gm += math_shrink(p);
2254 }
2255 break;
2256 }
2257 }
2258 break;
2259 default:
2260 break;
2261 }
2262 p = node_next(p);
2263 }
2264 switch (g_sign) {
2265 case stretching_glue_sign:
2266 wd += glueround((glueratio) (g_mult) * (glueratio) (gp));
2267 break;
2268 case shrinking_glue_sign:
2269 wd -= glueround((glueratio) (g_mult) * (glueratio) (gm));
2270 break;
2271 }
2272 return wd;
2273}
2274
2275halfword tex_natural_hsize(halfword p, halfword *correction)
2276{
2277 scaled wd = 0;
2278 halfword c = null;
2279 while (p) {
2280 switch (node_type(p)) {
2281 case glyph_node:
2282 wd += tex_glyph_width(p);
2283 break;
2284 case hlist_node:
2285 case vlist_node:
2286 case unset_node:
2287 wd += box_width(p);
2288 break;
2289 case rule_node:
2290 wd += rule_width(p);
2291 break;
2292 case glue_node:
2293 wd += glue_amount(p);
2294 if (node_subtype(p) == correction_skip_glue) {
2295 c = p;
2296 }
2297 break;
2298 case kern_node:
2299 wd += kern_amount(p);
2300 break;
2301 case disc_node:
2302 wd += tex_natural_hsize(disc_no_break(p), NULL);
2303 break;
2304 case math_node:
2305 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2306 wd += math_surround(p);
2307 } else {
2308 wd += math_amount(p);
2309 }
2310 break;
2311 default:
2312 break;
2313 }
2314 p = node_next(p);
2315 }
2316 if (correction) {
2317 *correction = c;
2318 }
2319 return wd;
2320}
2321
2322halfword tex_natural_vsize(halfword p)
2323{
2324 scaled ht = 0;
2325 scaled dp = 0;
2326 while (p) {
2327 switch (node_type(p)) {
2328 case hlist_node:
2329 case vlist_node:
2330 ht += dp + box_height(p);
2331 dp = box_depth(p);
2332 break;
2333 case unset_node:
2334 ht += dp + box_height(p);
2335 dp = box_depth(p);
2336 break;
2337 case rule_node:
2338 ht += dp + rule_height(p);
2339 dp = rule_depth(p);
2340 break;
2341 case glue_node:
2342 ht += dp + glue_amount(p);
2343 dp = 0;
2344 break;
2345 case kern_node:
2346 ht += dp + kern_amount(p);
2347 dp = 0;
2348 break;
2349 default:
2350 break;
2351 }
2352 p = node_next(p);
2353 }
2354 return ht + dp;
2355}
2356
2357
2367
2368halfword tex_vpack(halfword p, scaled targetheight, int m, scaled targetdepth, singleword pack_direction, int retain, scaled *excess)
2369{
2370 scaled width = 0;
2371 scaled depth = 0;
2372 scaled height = 0;
2373 int has_uleader = 0;
2374
2375 halfword box = tex_new_node(vlist_node, unknown_list);
2376 int has_limit = box_limit_mode_vlist ? 1 : -1;
2377 (void) retain;
2378 box_dir(box) = pack_direction;
2379 box_shift_amount(box) = 0;
2380 box_list(box) = p;
2381 lmt_packaging_state.last_badness = 0;
2382 lmt_packaging_state.last_overshoot = 0;
2383 for (int i = normal_glue_order; i <= filll_glue_order; i++) {
2384 lmt_packaging_state.total_stretch[i] = 0;
2385 lmt_packaging_state.total_shrink[i] = 0;
2386 }
2387 while (p) {
2388
2394 halfword n = node_next(p);
2395 switch (node_type(p)) {
2396 case hlist_node:
2397 case vlist_node:
2398 {
2399
2405 scaled shift = box_shift_amount(p);
2406 scaledwhd whd = tex_pack_dimensions(p);
2407 if (whd.wd + shift > width) {
2408 width = whd.wd + shift;
2409 }
2410 height += depth + whd.ht;
2411 depth = whd.dp;
2412 tex_aux_promote_pre_migrated(box, p);
2413 tex_aux_promote_post_migrated(box, p);
2414 }
2415 break;
2416 case unset_node:
2417 height += depth + box_height(p);
2418 depth = box_depth(p);
2419 if (box_width(p) > width) {
2420 width = box_width(p);
2421 }
2422
2423
2424 break;
2425 case rule_node:
2426 height += depth + rule_height(p);
2427 depth = rule_depth(p);
2428 if (rule_width(p) > width) {
2429 width = rule_width(p);
2430 }
2431 break;
2432 case glue_node:
2433
2434 {
2435 halfword o;
2436 height += depth + glue_amount(p);
2437 depth = 0;
2438 o = glue_stretch_order(p);
2439 lmt_packaging_state.total_stretch[o] += glue_stretch(p);
2440 o = glue_shrink_order(p);
2441 lmt_packaging_state.total_shrink[o] += glue_shrink(p);
2442 if (is_leader(p)) {
2443 halfword gl = glue_leader_ptr(p);
2444 scaled wd = 0;
2445 switch (node_type(gl)) {
2446 case hlist_node:
2447 case vlist_node:
2448 wd = box_width(gl);
2449 break;
2450 case rule_node:
2451 wd = rule_width(gl);
2452 break;
2453 }
2454 if (wd > width) {
2455 width = wd;
2456 }
2457 if (node_subtype(p) == u_leaders) {
2458 has_uleader = 1;
2459 }
2460 }
2461 if (! has_limit && tex_has_glue_option(p, glue_option_limit)) {
2462 has_limit = 1;
2463 }
2464 break;
2465 }
2466 case kern_node:
2467 height += depth + kern_amount(p);
2468 depth = 0;
2469 break;
2470 case insert_node:
2471 if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_insert)) {
2472 halfword l = insert_list(p);
2473 tex_aux_post_migrate(box, p);
2474 while (l) {
2475 l = node_type(l) == insert_node ? tex_aux_post_migrate(box, l) : node_next(l);
2476 }
2477 }
2478 break;
2479 case mark_node:
2480 if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_mark)) {
2481 tex_aux_post_migrate(box, p);
2482 }
2483 break;
2484 case glyph_node:
2485 tex_confusion("glyph in vpack");
2486 break;
2487 case disc_node:
2488 tex_confusion("discretionary in vpack");
2489 break;
2490 default:
2491 break;
2492 }
2493 p = n;
2494 }
2495 box_width(box) = width;
2496 if (depth > targetdepth) {
2497 height += depth - targetdepth;
2498 box_depth(box) = targetdepth;
2499 } else {
2500 box_depth(box) = depth;
2501 }
2502
2508 if (m == packing_additional) {
2509 targetheight += height;
2510 }
2511 box_height(box) = targetheight;
2512 {
2513 scaled targetexcess = targetheight - height;
2514
2515 if (excess) {
2516 *excess = targetexcess;
2517 }
2518 if (targetexcess == 0) {
2519 box_glue_sign(box) = normal_glue_sign;
2520 box_glue_order(box) = normal_glue_order;
2521 box_glue_set(box) = 0.0;
2522
2523 } else if (targetexcess > 0) {
2524
2525 halfword o = tex_aux_used_order(lmt_packaging_state.total_stretch);
2526 box_glue_order(box) = o;
2527 box_glue_sign(box) = stretching_glue_sign;
2528 if (lmt_packaging_state.total_stretch[o] != 0) {
2529 box_glue_set(box) = (glueratio) ((double) targetexcess / lmt_packaging_state.total_stretch[o]);
2530 } else {
2531
2532 box_glue_sign(box) = normal_glue_sign;
2533 box_glue_set(box) = 0.0;
2534 }
2535 if (o == normal_glue_order && box_list(box)) {
2536
2537 lmt_packaging_state.last_badness = tex_badness(targetexcess, lmt_packaging_state.total_stretch[normal_glue_order]);
2538 if (lmt_packaging_state.last_badness > vbadness_par) {
2539 int callback_id = lmt_callback_defined(vpack_quality_callback);
2540 if (callback_id > 0) {
2541 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2542 lmt_packaging_state.last_badness > 100 ? "underfull" : "loose",
2543 lmt_packaging_state.last_badness,
2544 box,
2545 abs(lmt_packaging_state.pack_begin_line),
2546 lmt_input_state.input_line,
2547 tex_current_input_file_name()
2548 );
2549
2550 } else {
2551 tex_print_nlp();
2552 if (lmt_packaging_state.last_badness > 100) {
2553 tex_print_format("%l[package: underfull \\vbox (badness %i)", lmt_packaging_state.last_badness);
2554 } else {
2555 tex_print_format("%l[package: loose \\vbox (badness %i)", lmt_packaging_state.last_badness);
2556 }
2557 goto COMMON_ENDING;
2558 }
2559 }
2560 }
2561
2562 } else {
2563
2564 halfword o = tex_aux_used_order(lmt_packaging_state.total_shrink);
2565 box_glue_order(box) = o;
2566 box_glue_sign(box) = shrinking_glue_sign;
2567 if (lmt_packaging_state.total_shrink[o] != 0) {
2568 box_glue_set(box) = (glueratio) ((double) (-targetexcess) / lmt_packaging_state.total_shrink[o]);
2569 } else {
2570
2571 box_glue_sign(box) = normal_glue_sign;
2572 box_glue_set(box) = 0.0;
2573 }
2574 if (o == normal_glue_order && box_list(box)) {
2575 if (lmt_packaging_state.total_shrink[o] < -targetexcess) {
2576 int overshoot = -targetexcess - lmt_packaging_state.total_shrink[normal_glue_order];
2577 lmt_packaging_state.last_badness = scaling_factor_squared;
2578 lmt_packaging_state.last_overshoot = overshoot;
2579
2580 box_glue_set(box) = 1.0;
2581
2582 if ((overshoot > vfuzz_par) || (vbadness_par < 100)) {
2583 int callback_id = lmt_callback_defined(vpack_quality_callback);
2584 if (callback_id > 0) {
2585 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2586 "overfull",
2587 overshoot,
2588 box,
2589 abs(lmt_packaging_state.pack_begin_line),
2590 lmt_input_state.input_line,
2591 tex_current_input_file_name()
2592 );
2593
2594 } else {
2595 tex_print_nlp();
2596 tex_print_format("%l[package: overfull \\vbox (%p too high)", - targetexcess - lmt_packaging_state.total_shrink[normal_glue_order]);
2597 goto COMMON_ENDING;
2598 }
2599 }
2600 } else {
2601
2602 lmt_packaging_state.last_badness = tex_badness(-targetexcess, lmt_packaging_state.total_shrink[normal_glue_order]);
2603 if (lmt_packaging_state.last_badness > vbadness_par) {
2604 int callback_id = lmt_callback_defined(vpack_quality_callback);
2605 if (callback_id > 0) {
2606 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2607 "tight",
2608 lmt_packaging_state.last_badness,
2609 box,
2610 abs(lmt_packaging_state.pack_begin_line),
2611 lmt_input_state.input_line,
2612 tex_current_input_file_name()
2613 );
2614
2615 } else {
2616 tex_print_nlp();
2617 tex_print_format("%l[package: tight \\vbox (badness %i)", lmt_packaging_state.last_badness);
2618 goto COMMON_ENDING;
2619 }
2620 }
2621 }
2622 }
2623
2624 }
2625 }
2626 goto EXIT;
2627 COMMON_ENDING:
2628
2629 if (lmt_page_builder_state.output_active) {
2630 tex_print_format(" has occurred while \\output is active]");
2631 } else if (lmt_packaging_state.pack_begin_line != 0) {
2632 tex_print_format(" in alignment at lines %i--%i]", abs(lmt_packaging_state.pack_begin_line), lmt_input_state.input_line);
2633 } else {
2634 tex_print_format(" detected at line %i]", lmt_input_state.input_line);
2635 }
2636 tex_print_ln();
2637 tex_begin_diagnostic();
2638 tex_show_box(box);
2639 tex_end_diagnostic();
2640 EXIT:
2641 if (has_uleader) {
2642 set_box_package_state(box, package_u_leader_found);
2643 }
2644 if (has_limit > 0) {
2645 tex_limit(box);
2646 }
2647
2648 return box;
2649}
2650
2651halfword tex_filtered_vpack(halfword p, scaled h, int m, scaled maxdepth, int grp, halfword direction, int just_pack, halfword attr, int state, int retain, int *excess)
2652{
2653 halfword result = p;
2654 if (! just_pack) {
2655
2656 if (result && normalize_line_mode_permitted(normalize_line_mode_par, flatten_h_leaders_mode)) {
2657 halfword c = result;
2658 while (c) {
2659 switch (node_type(c)) {
2660 case hlist_node:
2661 case vlist_node:
2662 if (has_box_package_state(c, package_u_leader_found)) {
2663 if (! is_box_package_state(state, package_u_leader_delayed)) {
2664 tex_flatten_leaders(c, grp, just_pack);
2665 }
2666 }
2667 break;
2668 }
2669 c = node_next(c);
2670 }
2671 }
2672 result = lmt_vpack_filter_callback(result, h, m, maxdepth, grp, direction, attr);
2673 }
2674 result = tex_vpack(result, h, m, maxdepth, (singleword) checked_direction_value(direction), retain, excess);
2675 if (result && normalize_par_mode_permitted(normalize_par_mode_par, flatten_v_leaders_mode) && ! is_box_package_state(state, package_u_leader_delayed)) {
2676 tex_flatten_leaders(result, grp, just_pack);
2677 }
2678 if (! just_pack) {
2679 result = lmt_packed_vbox_filter_callback(result, grp);
2680 }
2681 return result;
2682}
2683
2684static scaled tex_aux_first_height(halfword boxnode)
2685{
2686 halfword list = box_list(boxnode);
2687 if (list) {
2688 switch (node_type(list)) {
2689 case hlist_node:
2690 case vlist_node:
2691 return box_height(list);
2692 case rule_node:
2693 return rule_height(list);
2694 }
2695 }
2696 return 0;
2697}
2698
2699static void tex_aux_set_vnature(halfword boxnode, int nature)
2700{
2701 switch (nature) {
2702 case vtop_code:
2703 case tsplit_code:
2704 {
2705
2712 scaled height = tex_aux_first_height(boxnode);
2713 box_depth(boxnode) = box_total(boxnode) - height;
2714 box_height(boxnode) = height;
2715 box_package_state(boxnode) = vtop_package_state;
2716 }
2717 break;
2718 case vbox_code:
2719 case vsplit_code:
2720 box_package_state(boxnode) = vbox_package_state;
2721 break;
2722 case dbox_code:
2723 case dsplit_code:
2724 box_package_state(boxnode) = dbox_package_state;
2725 break;
2726 }
2727}
2728
2729
2730
2734
2735void tex_run_vcenter(void)
2736{
2737 tex_aux_scan_full_spec(direct_box_flag, vcenter_group, direction_l2r, 0, 0, -1, 0);
2738 tex_normal_paragraph(vcenter_par_context);
2739 tex_push_nest();
2740 cur_list.mode = internal_vmode;
2741 cur_list.prev_depth = ignore_depth_criterion_par;
2742 if (every_vbox_par) {
2743 tex_begin_token_list(every_vbox_par, every_vbox_text);
2744 }
2745}
2746
2747void tex_finish_vcenter_group(void)
2748{
2749 if (! tex_wrapped_up_paragraph(vcenter_par_context, 1)) {
2750 halfword p;
2751 tex_end_paragraph(vcenter_group, vcenter_par_context);
2752 tex_package(vbox_code);
2753 p = tex_pop_tail();
2754 if (p) {
2755 switch (node_type(p)) {
2756 case vlist_node:
2757 {
2758 scaled delta = box_total(p);
2759 box_height(p) = tex_half_scaled(delta);
2760 box_depth(p) = delta - box_height(p);
2761 break;
2762 }
2763 case simple_noad:
2764 node_subtype(p) = vcenter_noad_subtype;
2765 break;
2766
2770 }
2771 tex_tail_append(p);
2772 }
2773 }
2774}
2775
2776void tex_package(singleword nature)
2777{
2778 int grp = cur_group;
2779 scaled maxdepth = box_max_depth_par;
2780 tex_unsave();
2781 {
2782 lmt_save_state.save_stack_data.ptr -= saved_box_n_of_records;
2783 halfword boxnode = null;
2784
2788 halfword slot = saved_box_slot;
2789 halfword context = saved_box_context;
2790 halfword dirptr = saved_box_dir_pointer;
2791 halfword orientation = saved_box_orientation;
2792 halfword anchor = saved_box_anchor;
2793 halfword geometry = saved_box_geometry;
2794 halfword attrlist = saved_box_attr_list;
2795 halfword state = saved_box_state;
2796 scaled shift = saved_box_shift;
2797 halfword source = saved_box_source;
2798 halfword target = saved_box_target;
2799 halfword axis = saved_box_axis;
2800 halfword mainclass = saved_box_class;
2801 halfword callback = saved_box_callback;
2802 halfword option = saved_box_option;
2803 scaled xoffset = saved_box_xoffset;
2804 scaled yoffset = saved_box_yoffset;
2805 scaled xmove = saved_box_xmove;
2806 scaled ymove = saved_box_ymove;
2807 if (cur_list.mode == restricted_hmode) {
2808 boxnode = tex_filtered_hpack(
2809 cur_list.head, cur_list.tail,
2810 saved_box_amount, saved_box_packing, grp,
2811 saved_box_direction, saved_box_pack, attrlist, state, saved_box_retain
2812 );
2813 node_subtype(boxnode) = hbox_list;
2814 if (option & saved_box_reverse_option) {
2815 box_list(boxnode) = tex_reversed_node_list(box_list(boxnode));
2816 }
2817 box_package_state(boxnode) = hbox_package_state;
2818 } else {
2819 boxnode = tex_filtered_vpack(
2820 node_next(cur_list.head),
2821 saved_box_amount, saved_box_packing, maxdepth, grp,
2822 saved_box_direction, saved_box_pack, attrlist, state, saved_box_retain,
2823 NULL
2824 );
2825 box_package_state(boxnode) = hbox_package_state;
2826 tex_aux_set_vnature(boxnode, nature);
2827 }
2828 if (option & saved_box_limit_option && box_list(boxnode)) {
2829 tex_limit(boxnode);
2830 }
2831 if (dirptr) {
2832
2833 tex_flush_node_list(lmt_dir_state.text_dir_ptr);
2834 lmt_dir_state.text_dir_ptr = dirptr;
2835 }
2836
2841 tex_attach_attribute_list_attribute(boxnode, attrlist);
2842 delete_attribute_reference(attrlist);
2843
2844 if (tex_has_geometry(geometry, offset_geometry) || tex_has_geometry(geometry, orientation_geometry)) {
2845 scaled wd = box_width(boxnode);
2846 scaled ht = box_height(boxnode);
2847 scaled dp = box_depth(boxnode);
2848 if (xmove) {
2849 xoffset = tex_aux_checked_dimension1(xoffset + xmove);
2850 wd = tex_aux_checked_dimension2(wd + xmove);
2851 }
2852 if (ymove) {
2853 yoffset = tex_aux_checked_dimension1(yoffset + ymove);
2854 ht = tex_aux_checked_dimension2(ht + ymove);
2855 dp = tex_aux_checked_dimension2(dp - ymove);
2856 }
2857 box_w_offset(boxnode) = wd;
2858 box_h_offset(boxnode) = ht;
2859 box_d_offset(boxnode) = dp;
2860 switch (orientationonly(orientation)) {
2861 case 0 :
2862 break;
2863 case 2 :
2864 box_height(boxnode) = dp;
2865 box_depth(boxnode) = ht;
2866 geometry |= orientation_geometry;
2867 break;
2868 case 1 :
2869 case 3 :
2870 box_width(boxnode) = ht + dp;
2871 box_height(boxnode) = wd;
2872 box_depth(boxnode) = 0;
2873 geometry |= orientation_geometry;
2874 break;
2875 case 4 :
2876 box_height(boxnode) = ht + dp;
2877 box_depth(boxnode) = 0;
2878 geometry |= orientation_geometry;
2879 break;
2880 case 5 :
2881 box_height(boxnode) = 0;
2882 box_depth(boxnode) = ht + dp;
2883 geometry |= orientation_geometry;
2884 break;
2885 default :
2886 break;
2887 }
2888 if (xoffset || yoffset) {
2889 box_x_offset(boxnode) = xoffset;
2890 box_y_offset(boxnode) = yoffset;
2891 geometry |= offset_geometry;
2892 }
2893 }
2894 if (source || target) {
2895 box_source_anchor(boxnode) = source;
2896 box_target_anchor(boxnode) = target;
2897 geometry |= anchor_geometry;
2898 }
2899 box_anchor(boxnode) = anchor;
2900 box_orientation(boxnode) = orientation;
2901 box_geometry(boxnode) = (singleword) geometry;
2902 if (option & saved_box_container_option) {
2903 node_subtype(boxnode) = container_list;
2904 }
2905 box_axis(boxnode) = (singleword) axis;
2906 box_package_state(boxnode) |= (singleword) state;
2907 tex_pop_nest();
2908 tex_box_end(context, boxnode, shift, mainclass, slot, callback);
2909 }
2910}
2911
2912static int local_box_mapping[] = {
2913 [local_left_box_box_code ] = local_left_box_code,
2914 [local_right_box_box_code ] = local_right_box_code,
2915 [local_middle_box_box_code] = local_middle_box_code
2916};
2917
2918void tex_run_unpackage(void)
2919{
2920 int code = cur_chr;
2921 switch (code) {
2922 case box_code:
2923 case copy_code:
2924 case unpack_code:
2925 {
2926 halfword index = tex_scan_box_register_number();
2927 halfword box = box_register(index);
2928 if (box) {
2929 int bad = 0;
2930 switch (cur_list.mode) {
2931 case vmode:
2932 case internal_vmode:
2933 if (node_type(box) != vlist_node) {
2934 bad = 1;
2935 }
2936 break;
2937 case hmode:
2938 case restricted_hmode:
2939 if (node_type(box) != hlist_node) {
2940 bad = 1;
2941 }
2942 break;
2943 case mmode:
2944 case inline_mmode:
2945 bad = 1;
2946 break;
2947 }
2948 if (bad) {
2949 tex_handle_error(
2950 normal_error_type,
2951 "Incompatible list can't be unboxed",
2952 "Sorry, Pandora. (You sneaky devil.) I refuse to unbox an \\hbox in vertical mode\n"
2953 "or vice versa. And I can't open any boxes in math mode."
2954 );
2955 } else {
2956
2957
2958 halfword tail = cur_list.tail;
2959 halfword list = box_list(box);
2960 halfword pre_migrated = code == unpack_code ? null : box_pre_migrated(box);
2961 halfword post_migrated = code == unpack_code ? null : box_post_migrated(box);
2962
2963
2964
2965 halfword pre_adjusted = code == unpack_code ? null : box_pre_adjusted(box);
2966 halfword post_adjusted = code == unpack_code ? null : box_post_adjusted(box);
2967
2968
2969 int prunekerns = list && node_type(box) == hlist_node && normalize_line_mode_permitted(normalize_line_mode_par, remove_margin_kerns_mode);
2970
2979
3007 if (pre_adjusted) {
3008 if (code == copy_code) {
3009 pre_adjusted = tex_copy_node_list(pre_adjusted, null);
3010 } else {
3011 box_pre_adjusted(box) = null;
3012 }
3013 tail = tex_flush_adjust_prepend(pre_adjusted, tail);
3014 }
3015 if (pre_migrated) {
3016 if (code == copy_code) {
3017 pre_migrated = tex_copy_node_list(pre_migrated, null);
3018 } else {
3019 box_pre_migrated(box) = null;
3020 }
3021 tex_try_couple_nodes(tail, pre_migrated);
3022 tail = tex_tail_of_node_list(pre_migrated);
3023 }
3024 if (list) {
3025 if (code == copy_code) {
3026 list = tex_copy_node_list(list, null);
3027 } else {
3028 box_list(box) = null;
3029 }
3030 tex_try_couple_nodes(tail, list);
3031 tail = tex_tail_of_node_list(list);
3032 }
3033 if (post_migrated) {
3034 if (code == copy_code) {
3035 post_migrated = tex_copy_node_list(post_migrated, null);
3036 } else {
3037 box_post_migrated(box) = null;
3038 }
3039 tex_try_couple_nodes(tail, post_migrated);
3040 tail = tex_tail_of_node_list(post_migrated);
3041 }
3042 if (post_adjusted) {
3043 if (code == copy_code) {
3044 post_adjusted = tex_copy_node_list(post_adjusted, null);
3045 } else {
3046 box_post_adjusted(box) = null;
3047 }
3048 tail = tex_flush_adjust_append(post_adjusted, tail);
3049 }
3050 if (code != copy_code) {
3051 box_register(index) = null;
3052 tex_flush_node(box);
3053 }
3054 cur_list.tail = prunekerns ? tex_wipe_margin_kerns(cur_list.head) : tex_tail_of_node_list(tail);
3055 }
3056 }
3057 break;
3058 }
3059 case page_discards_code:
3060 {
3061 tex_try_couple_nodes(cur_list.tail, lmt_packaging_state.page_discards_head);
3062 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3063 lmt_packaging_state.page_discards_head = null;
3064 break;
3065 }
3066 case split_discards_code:
3067 {
3068 tex_try_couple_nodes(cur_list.tail, lmt_packaging_state.split_discards_head);
3069 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3070 lmt_packaging_state.split_discards_head = null;
3071 break;
3072 }
3073 case insert_box_code:
3074 case insert_copy_code:
3075 {
3076
3081 halfword index = tex_scan_integer(0, NULL);
3082 if (tex_valid_insert_id(index)) {
3083 halfword boxnode = tex_get_insert_content(index);
3084 if (boxnode) {
3085 if (! is_v_mode(cur_list.mode)) {
3086 tex_handle_error(
3087 normal_error_type,
3088 "Unpacking an inserts can only happen in vertical mode.",
3089 NULL
3090 );
3091 } else if (node_type(boxnode) == vlist_node) {
3092 if (code == insert_copy_code) {
3093 boxnode = tex_copy_node(boxnode);
3094 } else {
3095 tex_set_insert_content(index, null);
3096 }
3097 if (boxnode) {
3098 halfword list = box_list(boxnode);
3099 if (list) {
3100 tex_try_couple_nodes(cur_list.tail, list);
3101 cur_list.tail = tex_tail_of_node_list(list);
3102 box_list(boxnode) = null;
3103 }
3104 tex_flush_node(boxnode);
3105 }
3106 } else {
3107
3108 }
3109 }
3110 }
3111 break;
3112 }
3113 case local_left_box_box_code:
3114 case local_right_box_box_code:
3115 case local_middle_box_box_code:
3116 {
3117 tex_try_couple_nodes(cur_list.tail, tex_get_local_boxes(local_box_mapping[code]));
3118 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3119 break;
3120 }
3121 default:
3122 {
3123 tex_confusion("weird unpackage");
3124 break;
3125 }
3126 }
3127}
3128
3129
3139
3140static halfword tex_aux_depth_correction(halfword b, const line_break_properties *properties)
3141{
3142
3143 halfword p;
3144 halfword height = has_box_package_state(b, dbox_package_state) ? tex_aux_first_height(b) : box_height(b);
3145 halfword depth = cur_list.prev_depth;
3146 if (properties) {
3147 scaled d = glue_amount(properties->baseline_skip) - depth - height;
3148 if (d < properties->line_skip_limit) {
3149 p = tex_new_glue_node(properties->line_skip, line_skip_glue);
3150 } else {
3151 p = tex_new_glue_node(properties->baseline_skip, baseline_skip_glue);
3152 glue_amount(p) = d;
3153 }
3154 } else {
3155 scaled d = glue_amount(baseline_skip_par) - depth - height;
3156 if (d < line_skip_limit_par) {
3157 p = tex_new_param_glue_node(line_skip_code, line_skip_glue);
3158 } else {
3159 p = tex_new_param_glue_node(baseline_skip_code, baseline_skip_glue);
3160 glue_amount(p) = d;
3161 }
3162 }
3163 return p;
3164}
3165
3166void tex_append_to_vlist(halfword b, int location, const line_break_properties *properties)
3167{
3168 if (location >= 0) {
3169 halfword result = null;
3170 halfword next_depth = ignore_depth_criterion_par;
3171 int prev_set = 0;
3172 int check_depth = 0;
3173 if (lmt_append_to_vlist_callback(b, location, cur_list.prev_depth, &result, &next_depth, &prev_set, &check_depth)) {
3174 if (prev_set) {
3175 cur_list.prev_depth = next_depth;
3176 }
3177 if (check_depth && result && (cur_list.prev_depth > ignore_depth_criterion_par)) {
3178
3182 switch (node_type(result)) {
3183 case hlist_node:
3184 case vlist_node:
3185 case rule_node:
3186 {
3187 halfword glue = tex_aux_depth_correction(result, properties);
3188 tex_tail_append(glue);
3189 break;
3190 }
3191 }
3192 }
3193 if (result) {
3194 tex_tail_append_list(result);
3195 }
3196 return;
3197 }
3198 }
3199 if (cur_list.prev_depth > ignore_depth_criterion_par) {
3200 halfword glue = tex_aux_depth_correction(b, properties);
3201 tex_tail_append(glue);
3202 }
3203 tex_tail_append(b);
3204 cur_list.prev_depth = box_depth(b);
3205}
3206
3207
3230
3231halfword tex_prune_page_top(halfword p, int s)
3232{
3233
3234 halfword prev_p = temp_head;
3235 halfword r = null;
3236 node_next(temp_head) = p;
3237 while (p) {
3238 switch (node_type(p)) {
3239 case hlist_node:
3240 case vlist_node:
3241 case rule_node:
3242 {
3243
3244 halfword h = node_type(p) == rule_node ? rule_height(p) : box_height(p);
3245 halfword q = tex_new_param_glue_node(split_top_skip_code, split_top_skip_glue);
3246 node_next(prev_p) = q;
3247 node_next(q) = p;
3248 glue_amount(q) = glue_amount(q) > h ? glue_amount(q) - h : 0;
3249 p = null;
3250 }
3251 break;
3252 case boundary_node:
3253
3254 case whatsit_node:
3255 case mark_node:
3256 case insert_node:
3257 prev_p = p;
3258 p = node_next(prev_p);
3259 break;
3260 case glue_node:
3261 case kern_node:
3262 case penalty_node:
3263 {
3264 halfword q = p;
3265 p = node_next(q);
3266 node_next(q) = null;
3267 node_next(prev_p) = p;
3268 if (s) {
3269 if (lmt_packaging_state.split_discards_head) {
3270 node_next(r) = q;
3271 } else {
3272 lmt_packaging_state.split_discards_head = q;
3273 }
3274 r = q;
3275 } else {
3276 tex_flush_node_list(q);
3277 }
3278 }
3279 break;
3280 default:
3281 tex_confusion("pruning page top");
3282 break;
3283 }
3284 }
3285 return node_next(temp_head);
3286}
3287
3288
3311
3312static halfword tex_aux_vert_badness(scaled goal, scaled active_height[])
3313{
3314 if (active_height[total_advance_amount] < goal) {
3315 if (active_height[total_fi_amount] || active_height[total_fil_amount] || active_height[total_fill_amount] || active_height[total_filll_amount]) {
3316 return 0;
3317 } else {
3318 return tex_badness(goal - active_height[total_advance_amount], active_height[total_stretch_amount]);
3319 }
3320 } else if (active_height[total_advance_amount] - goal > active_height[total_shrink_amount]) {
3321 return awful_bad;
3322 } else {
3323 return tex_badness(active_height[total_advance_amount] - goal, active_height[total_shrink_amount]);
3324 }
3325}
3326
3327static halfword tex_aux_vert_costs(halfword badness, halfword penalty)
3328{
3329 if (badness >= awful_bad) {
3330 return badness;
3331 } else if (penalty <= eject_penalty) {
3332 return penalty;
3333 } else if (badness < infinite_bad) {
3334 return badness + penalty;
3335 } else {
3336 return deplorable;
3337 }
3338}
3339
3340halfword tex_vert_break(halfword current, scaled height, scaled depth)
3341{
3342
3346 halfword previous = current;
3347
3348 halfword penalty = 0;
3349
3350 halfword least_cost = awful_bad;
3351
3352 halfword best_place = null;
3353
3354 scaled previous_depth = 0;
3355
3356 scaled active_height[10] = { 0 };
3357 while (1) {
3358
3365 if (current) {
3366
3371 switch (node_type(current)) {
3372 case hlist_node:
3373 case vlist_node:
3374
3378
3387 active_height[total_advance_amount] += previous_depth + box_height(current);
3388 previous_depth = box_depth(current);
3389 goto NOT_FOUND;
3390 case rule_node:
3391 active_height[total_advance_amount] += previous_depth + rule_height(current);
3392 previous_depth = rule_depth(current);
3393 goto NOT_FOUND;
3394 case boundary_node:
3395 case whatsit_node:
3396 goto NOT_FOUND;
3397 case glue_node:
3398 if (precedes_break(previous)) {
3399 penalty = 0;
3400 break;
3401 } else {
3402 goto UPDATE_HEIGHTS;
3403 }
3404 case kern_node:
3405 if (node_next(current) && node_type(node_next(current)) == glue_node) {
3406 penalty = 0;
3407 break;
3408 } else {
3409 goto UPDATE_HEIGHTS;
3410 }
3411 case penalty_node:
3412 penalty = penalty_amount(current);
3413
3414 break;
3415 case mark_node:
3416 case insert_node:
3417 goto NOT_FOUND;
3418 default:
3419 tex_confusion("vertical break");
3420 break;
3421 }
3422 } else {
3423 penalty = eject_penalty;
3424 }
3425
3429 if (penalty < infinite_penalty) {
3430
3431 int badness = tex_aux_vert_badness(height, active_height);
3432 int costs = tex_aux_vert_costs(badness, penalty);
3433 if (costs <= least_cost) {
3434 best_place = current;
3435 least_cost = costs;
3436 lmt_packaging_state.best_height_plus_depth = active_height[total_advance_amount] + previous_depth;
3437
3441 if (lmt_packaging_state.best_height_plus_depth > (height + previous_depth) && costs < awful_bad) {
3442 lmt_packaging_state.best_height_plus_depth = height + previous_depth;
3443 }
3444 }
3445 if ((costs == awful_bad) || (penalty <= eject_penalty)) {
3446 return best_place;
3447 }
3448 }
3449 UPDATE_HEIGHTS:
3450
3456 switch(node_type(current)) {
3457 case kern_node:
3458 active_height[total_advance_amount] += previous_depth + kern_amount(current);
3459 previous_depth = 0;
3460 goto KEEP_GOING;
3461 case glue_node:
3462 active_height[total_stretch_amount + glue_stretch_order(current)] += glue_stretch(current);
3463 active_height[total_shrink_amount] += glue_shrink(current);
3464 if (glue_shrink_order(current) != normal_glue_order && glue_shrink(current)) {
3465 tex_handle_error(
3466 normal_error_type,
3467 "Infinite glue shrinkage found in box being split",
3468 "The box you are \\vsplitting contains some infinitely shrinkable glue, e.g.,\n"
3469 "'\\vss' or '\\vskip 0pt minus 1fil'. Such glue doesn't belong there; but you can\n"
3470 "safely proceed, since the offensive shrinkability has been made finite."
3471 );
3472 glue_shrink_order(current) = normal_glue_order;
3473 }
3474 active_height[total_advance_amount] += previous_depth+ glue_amount(current);
3475 previous_depth = 0;
3476 goto KEEP_GOING;
3477 }
3478 NOT_FOUND:
3479 if (previous_depth > depth) {
3480 active_height[total_advance_amount] += previous_depth - depth;
3481 previous_depth = depth;
3482 }
3483 KEEP_GOING:
3484 previous = current;
3485 current = node_next(previous);
3486 }
3487 return best_place;
3488}
3489
3490
3508
3509halfword tex_vsplit(halfword n, scaled h, int m)
3510{
3511
3512 halfword v = box_register(n);
3513 tex_flush_node_list(lmt_packaging_state.split_discards_head);
3514 lmt_packaging_state.split_discards_head = null;
3515 for (halfword i = 0; i <= lmt_mark_state.mark_data.ptr; i++) {
3516 tex_delete_mark(i, split_first_mark_code);
3517 tex_delete_mark(i, split_bot_mark_code);
3518 }
3519
3520 if (! v) {
3521 return null;
3522 } else if (node_type(v) != vlist_node) {
3523 tex_handle_error(
3524 normal_error_type,
3525 "\\vsplit needs a \\vbox",
3526 "The box you are trying to split is an \\hbox. I can't split such a box, so I''ll\n"
3527 "leave it alone."
3528 );
3529 return null;
3530 } else {
3531
3532 halfword q = tex_vert_break(box_list(v), h, split_max_depth_par);
3533
3540 halfword p = box_list(v);
3541
3542 int vdir = box_dir(v);
3543 if (p == q) {
3544 box_list(v) = null;
3545 } else {
3546 while (1) {
3547 if (node_type(p) == mark_node) {
3548 tex_update_split_mark(p);
3549 }
3550 if (node_next(p) == q) {
3551 node_next(p) = null;
3552 break;
3553 } else {
3554 p = node_next(p);
3555 }
3556 }
3557 }
3558 q = tex_prune_page_top(q, saving_vdiscards_par > 0);
3559 p = box_list(v);
3560 box_list(v) = null;
3561 tex_flush_node(v);
3562 if (q) {
3563 box_register(n) = tex_filtered_vpack(q, 0, packing_additional, max_depth_par, split_keep_group, vdir, 0, 0, 0, holding_none_option, NULL);
3564 } else {
3565
3566 box_register(n) = null;
3567 }
3568 return tex_filtered_vpack(p, m == packing_additional ? 0 : h, m, max_depth_par, split_off_group, vdir, 0, 0, 0, holding_none_option, NULL);
3569 }
3570}
3571
3572
3579
3580void tex_begin_box(int boxcontext, scaled shift, halfword slot, halfword callback)
3581{
3582 halfword code = cur_chr;
3583 halfword boxnode = null;
3584 switch (code) {
3585 case box_code:
3586 {
3587 halfword n = tex_scan_box_register_number();
3588 boxnode = box_register(n);
3589
3590 box_register(n) = null;
3591 break;
3592 }
3593 case copy_code:
3594 {
3595 halfword n = tex_scan_box_register_number();
3596 boxnode = box_register(n) ? tex_copy_node(box_register(n)) : null;
3597 break;
3598 }
3599
3600
3601 case last_box_code:
3602
3606 boxnode = null;
3607 if (is_m_mode(cur_list.mode)) {
3608 tex_you_cant_error(
3609 "Sorry; this \\lastbox will be void."
3610 );
3611 } else if (cur_list.mode == vmode && cur_list.head == cur_list.tail) {
3612 tex_you_cant_error(
3613 "Sorry...I usually can't take things from the current page.\n"
3614 "This \\lastbox will therefore be void."
3615 );
3616 } else if (cur_list.head != cur_list.tail) {
3617 switch (node_type(cur_list.tail)) {
3618 case hlist_node:
3619 case vlist_node:
3620 {
3621
3622 halfword q = node_prev(cur_list.tail);
3623 if (! q || node_next(q) != cur_list.tail) {
3624 q = cur_list.head;
3625 while (node_next(q) != cur_list.tail)
3626 q = node_next(q);
3627 }
3628 tex_uncouple_node(cur_list.tail);
3629 boxnode = cur_list.tail;
3630 box_shift_amount(boxnode) = 0;
3631 cur_list.tail = q;
3632 node_next(cur_list.tail) = null;
3633 }
3634 break;
3635 }
3636 }
3637 break;
3638 case tsplit_code:
3639 case vsplit_code:
3640 case dsplit_code:
3641 {
3642
3647 halfword mode = packing_exactly ;
3648 halfword index = tex_scan_box_register_number();
3649 halfword size = 0;
3650 halfword attrlist = null;
3651 while (1) {
3652 switch (tex_scan_character("atuATU", 0, 1, 0)) {
3653 case 0:
3654 goto DONE;
3655 case 'a': case 'A':
3656 if (tex_scan_mandate_keyword("attr", 1)) {
3657 attrlist = tex_scan_attribute(attrlist);
3658 }
3659 break;
3660 case 't': case 'T':
3661 if (tex_scan_mandate_keyword("to", 1)) {
3662 mode = packing_exactly ;
3663 size = tex_scan_dimension(0, 0, 0, 0, NULL);
3664 }
3665 break;
3666 case 'u': case 'U':
3667 if (tex_scan_mandate_keyword("upto", 1)) {
3668 mode = packing_additional;
3669 size = tex_scan_dimension(0, 0, 0, 0, NULL);
3670 }
3671 break;
3672 default:
3673 tex_aux_show_keyword_error("attr|upto|to");
3674 goto DONE;
3675 }
3676 }
3677 DONE:
3678 boxnode = tex_vsplit(index, size, mode);
3679 tex_aux_set_vnature(boxnode, code);
3680 if (attrlist) {
3681 tex_attach_attribute_list_attribute(boxnode, attrlist);
3682 }
3683 }
3684 break;
3685 case insert_box_code:
3686 case insert_copy_code:
3687 {
3688 halfword index = tex_scan_integer(0, NULL);
3689 if (tex_valid_insert_id(index)) {
3690 boxnode = tex_get_insert_content(index);
3691 if (boxnode) {
3692 if (node_type(boxnode) == vlist_node) {
3693 if (code == insert_copy_code) {
3694 boxnode = tex_copy_node(boxnode);
3695 } else {
3696 tex_set_insert_content(index, null);
3697 }
3698 } else {
3699 tex_set_insert_content(index, null);
3700
3701 }
3702 }
3703 }
3704 break;
3705 }
3706 case local_left_box_box_code:
3707 {
3708 boxnode = tex_get_local_boxes(local_left_box_code);
3709 break;
3710 }
3711 case local_right_box_box_code:
3712 {
3713 boxnode = tex_get_local_boxes(local_right_box_code);
3714 break;
3715 }
3716 case local_middle_box_box_code:
3717 {
3718 boxnode = tex_get_local_boxes(local_middle_box_code);
3719 break;
3720 }
3721
3728 default:
3729 {
3730 quarterword direction;
3731 int justpack = 0;
3732 quarterword group = vbox_group;
3733 int mode = vmode;
3734 int adjusted = 0;
3735 switch (cur_list.mode) {
3736 case vmode:
3737 case internal_vmode:
3738 direction = dir_lefttoright;
3739 if (boxcontext == direct_box_flag) {
3740 adjusted = 1;
3741 }
3742 break;
3743 case hmode:
3744 case restricted_hmode:
3745 direction = (singleword) text_direction_par;
3746 break;
3747 case mmode:
3748 case inline_mmode:
3749 direction = (singleword) math_direction_par;
3750 break;
3751 default:
3752 direction = direction_unknown;
3753 break;
3754 }
3755 switch (code) {
3756 case tpack_code:
3757
3758 justpack = 1;
3759 group = vtop_group;
3760 break;
3761 case vpack_code:
3762
3763 justpack = 1;
3764
3765 break;
3766 case hpack_code:
3767 mode = hmode;
3768 justpack = 1;
3769 group = adjusted ? adjusted_hbox_group : hbox_group;
3770 break;
3771 case dpack_code:
3772
3773 justpack = 1;
3774 group = dbox_group;
3775 break;
3776 case vtop_code:
3777
3778
3779 group = vtop_group;
3780 break;
3781 case vbox_code:
3782
3783
3784
3785 break;
3786 case hbox_code:
3787 mode = hmode;
3788
3789 group = adjusted ? adjusted_hbox_group : hbox_group;
3790 break;
3791 case dbox_code:
3792
3793
3794 group = dbox_group;
3795 break;
3796 }
3797 tex_aux_scan_full_spec(boxcontext, group, direction, justpack, shift, slot, callback);
3798 tex_normal_paragraph(vmode_par_context);
3799 tex_push_nest();
3800 update_tex_internal_dir_state(0);
3801 cur_list.mode = - mode;
3802 if (mode == vmode) {
3803 cur_list.prev_depth = ignore_depth_criterion_par;
3804 if (every_vbox_par) {
3805 tex_begin_token_list(every_vbox_par, every_vbox_text);
3806 }
3807 } else {
3808 cur_list.space_factor = default_space_factor;
3809 if (every_hbox_par) {
3810 tex_begin_token_list(every_hbox_par, every_hbox_text);
3811 }
3812 }
3813 return;
3814 }
3815 }
3816
3817 tex_box_end(boxcontext, boxnode, shift, unset_noad_class, slot, callback);
3818}
3819 |