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_options_entry = 7,
94 saved_box_reserved_1_entry = 7,
95 saved_box_callback_entry = 8,
96 saved_box_leaders_entry = 8,
97 saved_box_reserved_2_entry = 8,
98 saved_box_n_of_records = 9,
99} saved_box_entries;
100
101typedef enum saved_box_options {
102 saved_box_reverse_option = 0x01,
103 saved_box_container_option = 0x02,
104 saved_box_limit_option = 0x04,
105 saved_box_mathtext_option = 0x08,
106 saved_box_discardable_option = 0x10,
107} saved_box_options;
108
109static inline void saved_box_initialize(void)
110{
111 saved_type(0) = saved_record_0;
112 saved_type(1) = saved_record_1;
113 saved_type(2) = saved_record_2;
114 saved_type(3) = saved_record_3;
115 saved_type(4) = saved_record_4;
116 saved_type(5) = saved_record_5;
117 saved_type(6) = saved_record_6;
118 saved_type(7) = saved_record_7;
119 saved_type(8) = saved_record_8;
120 saved_record(0) = box_save_type;
121 saved_record(1) = box_save_type;
122 saved_record(2) = box_save_type;
123 saved_record(3) = box_save_type;
124 saved_record(4) = box_save_type;
125 saved_record(5) = box_save_type;
126 saved_record(6) = box_save_type;
127 saved_record(7) = box_save_type;
128 saved_record(8) = box_save_type;
129}
130
131# define saved_box_slot saved_value_1(saved_box_slot_entry)
132# define saved_box_context saved_value_2(saved_box_context_entry)
133# define saved_box_packing saved_value_3(saved_box_packing_entry)
134# define saved_box_amount saved_value_1(saved_box_amount_entry)
135# define saved_box_direction saved_value_2(saved_box_direction_entry)
136# define saved_box_dir_pointer saved_value_3(saved_box_dir_pointer_entry)
137# define saved_box_attr_list saved_value_1(saved_box_attr_list_entry)
138# define saved_box_pack saved_value_2(saved_box_pack_entry)
139# define saved_box_orientation saved_value_3(saved_box_orientation_entry)
140# define saved_box_anchor saved_value_1(saved_box_anchor_entry)
141# define saved_box_geometry saved_value_2(saved_box_geometry_entry)
142# define saved_box_xoffset saved_value_3(saved_box_xoffset_entry)
143# define saved_box_yoffset saved_value_1(saved_box_yoffset_entry)
144# define saved_box_xmove saved_value_2(saved_box_xmove_entry)
145# define saved_box_ymove saved_value_3(saved_box_ymove_entry)
146# define saved_box_shift saved_value_1(saved_box_shift_entry)
147# define saved_box_source saved_value_2(saved_box_source_entry)
148# define saved_box_target saved_value_3(saved_box_target_entry)
149# define saved_box_class saved_value_1(saved_box_class_entry)
150# define saved_box_state saved_value_2(saved_box_state_entry)
151# define saved_box_axis saved_value_3(saved_box_axis_entry)
152# define saved_box_retain saved_value_1(saved_box_retain_entry)
153# define saved_box_options saved_value_2(saved_box_options_entry)
154# define saved_box_reserved_1 saved_value_3(saved_box_reserved_1_entry)
155# define saved_box_callback saved_value_1(saved_box_callback_entry)
156# define saved_box_leaders saved_value_2(saved_box_leaders_entry)
157# define saved_box_reserved_2 saved_value_3(saved_box_reserved_2_entry)
158
159void tex_show_packaging_group(const char *package)
160{
161 tex_print_str_esc(package);
162 tex_print_str(saved_box_packing == packing_exactly ? " to " : " spread ");
163 tex_print_dimension(saved_box_amount, pt_unit);
164}
165
166int tex_show_packaging_record(void)
167{
168 tex_print_str("box, ");
169 switch (saved_type(0)) {
170 case saved_record_0:
171 tex_print_format("slot %i, context %i, packing %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
172 break;
173 case saved_record_1:
174 tex_print_format("amount %p, direction %i, pointer %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
175 break;
176 case saved_record_2:
177 tex_print_format("attrlist %i, pack %i, orientation %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
178 break;
179 case saved_record_3:
180 tex_print_format("anchor %i, geometry %i, xoffset %p", saved_value_1(0), saved_value_2(0), saved_value_3(0));
181 break;
182 case saved_record_4:
183 tex_print_format("yoffset %p, xmove %p, ymove %p", saved_value_1(0), saved_value_2(0), saved_value_3(0));
184 break;
185 case saved_record_5:
186 tex_print_format("shift %p, source %i, target %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
187 break;
188 case saved_record_6:
189 tex_print_format("class %i, state %i, axis %i", saved_value_1(0), saved_value_2(0), saved_value_3(0));
190 break;
191 case saved_record_7:
192 tex_print_format("retain %i, options %i", saved_value_1(0), saved_value_2(0));
193 break;
194 case saved_record_8:
195 tex_print_format("callback %i, leaders %i", saved_value_1(0), saved_value_2(0));
196 break;
197 default:
198 return 0;
199 }
200 return 1;
201}
202
203int tex_get_packaging_context(void) { return saved_box_context; }
204int tex_get_packaging_shift (void) { return saved_box_shift; }
205
206static void tex_aux_scan_full_spec(halfword context, quarterword c, quarterword spec_direction, int just_pack, scaled shift, halfword slot, halfword callback, halfword leaders)
207{
208 quarterword spec_packing = packing_additional;
209 int spec_amount = 0;
210 halfword attrlist = null;
211 halfword orientation = 0;
212 scaled xoffset = 0;
213 scaled yoffset = 0;
214 scaled xmove = 0;
215 scaled ymove = 0;
216 halfword source = 0;
217 halfword target = 0;
218 halfword anchor = 0;
219 halfword geometry = 0;
220 halfword axis = 0;
221 halfword state = 0;
222 halfword retain = 0;
223 halfword mainclass = unset_noad_class;
224 halfword options = 0;
225 int brace = 0;
226 while (1) {
227
228 switch (tex_scan_character("tascdoxyrlmTASCDOXYRLM", 1, 1, 1)) {
229 case 0:
230 goto DONE;
231 case 't': case 'T':
232 switch (tex_scan_character("aoAO", 0, 0, 0)) {
233 case 'a': case 'A':
234 if (tex_scan_mandate_keyword("target", 2)) {
235 target = tex_scan_integer(1, NULL, NULL);
236 }
237 break;
238 case 'o': case 'O':
239 spec_packing = packing_exactly;
240 spec_amount = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
241 break;
242 default:
243 tex_aux_show_keyword_error("target|to");
244 goto DONE;
245 }
246 break;
247 case 'a': case 'A':
248 switch (tex_scan_character("dntxDNTX", 0, 0, 0)) {
249 case 'd': case 'D':
250 if (tex_scan_mandate_keyword("adapt", 2)) {
251 spec_packing = packing_adapted;
252 spec_amount = tex_scan_limited_scale(0);
253 }
254 break;
255 case 't': case 'T':
256 if (tex_scan_mandate_keyword("attr", 2)) {
257 attrlist = tex_scan_attribute(attrlist);
258 }
259 break;
260 case 'n': case 'N':
261 if (tex_scan_mandate_keyword("anchor", 2)) {
262 switch (tex_scan_character("sS", 0, 0, 0)) {
263 case 's': case 'S':
264 anchor = tex_scan_anchors(0);
265 break;
266 default:
267 anchor = tex_scan_anchor(0);
268 break;
269 }
270 }
271 break;
272 case 'x': case 'X':
273 if (tex_scan_mandate_keyword("axis", 2)) {
274 axis = tex_scan_box_axis();
275 }
276 break;
277 default:
278 tex_aux_show_keyword_error("adapt|attr|anchor|axis");
279 goto DONE;
280 }
281 break;
282 case 's': case 'S':
283 switch (tex_scan_character("hpoHPO", 0, 0, 0)) {
284 case 'h': case 'H':
285
290 if (tex_scan_mandate_keyword("shift", 2)) {
291 shift = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
292 }
293 break;
294 case 'p': case 'P':
295 if (tex_scan_mandate_keyword("spread", 2)) {
296 spec_packing = packing_additional;
297 spec_amount = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
298 }
299 break;
300 case 'o': case 'O':
301 if (tex_scan_mandate_keyword("source", 2)) {
302 source = tex_scan_integer(1, NULL, NULL);
303 }
304 break;
305 default:
306 tex_aux_show_keyword_error("shift|spread|source");
307 goto DONE;
308 }
309 break;
310 case 'd': case 'D':
311 switch (tex_scan_character("eiEI", 0, 0, 0)) {
312 case 'i': case 'I':
313
318# if (0)
319 if (tex_scan_mandate_keyword("direction", 2)) {
320 spec_direction = tex_scan_direction(0);
321 }
322# else
323 if (tex_scan_keyword("rection")) {
324 spec_direction = tex_scan_direction(0);
325} else if (tex_scan_keyword("scardable")) {
326 options |= saved_box_discardable_option;
327 } else if (tex_scan_character("rR", 0, 0, 0)) {
328
329 if (tex_scan_character("tT", 0, 1, 0)) {
330 switch (tex_scan_character("lLrR", 0, 0, 0)) {
331 case 'l': case 'L':
332 spec_direction = 0;
333 break;
334 case 'r': case 'R':
335 spec_direction = 1;
336 break;
337 default:
338 goto BADDIR;
339 }
340 if (! tex_scan_character("tT", 0, 0, 0)) {
341 goto BADDIR;
342 }
343 } else {
344 BADDIR:
345 tex_aux_show_keyword_error("tlt|trt");
346 goto DONE;
347 }
348 } else {
349
350tex_aux_show_keyword_error("direction|dir|discardable");
351 goto DONE;
352 }
353# endif
354 break;
355 case 'e': case 'E':
356 if (tex_scan_mandate_keyword("delay", 2)) {
357 state |= package_u_leader_delayed;
358 }
359 break;
360 default:
361 tex_aux_show_keyword_error("direction|delay");
362 goto DONE;
363 }
364 break;
365 case 'o': case 'O':
366 if (tex_scan_mandate_keyword("orientation", 1)) {
367 orientation = tex_scan_orientation(0);
368 }
369 break;
370 case 'x': case 'X':
371 switch (tex_scan_character("omOM", 0, 0, 0)) {
372 case 'o': case 'O' :
373 if (tex_scan_mandate_keyword("xoffset", 2)) {
374 xoffset = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
375 }
376 break;
377 case 'm': case 'M' :
378 if (tex_scan_mandate_keyword("xmove", 2)) {
379 xmove = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
380 }
381 break;
382 default:
383 tex_aux_show_keyword_error("xoffset|xmove");
384 goto DONE;
385 }
386 break;
387 case 'y': case 'Y':
388 switch (tex_scan_character("omOM", 0, 0, 0)) {
389 case 'o': case 'O' :
390 if (tex_scan_mandate_keyword("yoffset", 2)) {
391 yoffset = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
392 }
393 break;
394 case 'm': case 'M' :
395 if (tex_scan_mandate_keyword("ymove", 2)) {
396 ymove = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
397 }
398 break;
399 default:
400 tex_aux_show_keyword_error("yoffset|ymove");
401 goto DONE;
402 }
403 break;
404 case 'r': case 'R':
405 if (tex_scan_character("eE", 0, 0, 0)) {
406 switch (tex_scan_character("vVtT", 0, 0, 0)) {
407 case 'v': case 'V' :
408 if (tex_scan_mandate_keyword("reverse", 3)) {
409 options |= saved_box_reverse_option;
410 }
411 break;
412 case 't': case 'T' :
413 if (tex_scan_mandate_keyword("retain", 3)) {
414 retain = tex_scan_integer(0, NULL, NULL);
415 }
416 break;
417 default:
418 tex_aux_show_keyword_error("reverse|retain");
419 goto DONE;
420 }
421 }
422 break;
423 case 'c': case 'C':
424 switch (tex_scan_character("olOL", 0, 0, 0)) {
425 case 'o': case 'O' :
426 if (tex_scan_mandate_keyword("container", 2)) {
427 options |= saved_box_container_option;
428 }
429 break;
430 case 'l': case 'L' :
431 if (tex_scan_mandate_keyword("class", 2)) {
432 mainclass = tex_scan_math_class_number(0);
433 }
434 break;
435 default:
436 tex_aux_show_keyword_error("container|class");
437 goto DONE;
438 }
439 break;
440 case 'l': case 'L':
441 if (tex_scan_mandate_keyword("limit", 1)) {
442 options |= saved_box_limit_option;
443 }
444 break;
445 case 'm': case 'M':
446 if (tex_scan_mandate_keyword("mathtext", 1)) {
447 options |= saved_box_mathtext_option;
448 }
449 break;
450 case '{':
451 brace = 1;
452 goto DONE;
453 default:
454 goto DONE;
455 }
456 }
457 DONE:
458 if (anchor || source || target) {
459 geometry |= anchor_geometry;
460 }
461 if (orientation || xmove || ymove) {
462 geometry |= orientation_geometry;
463 }
464 if (xoffset || yoffset) {
465 geometry |= offset_geometry;
466 }
467
472 if (! attrlist) {
473
474 attrlist = tex_current_attribute_list();
475 }
476
477 add_attribute_reference(attrlist);
478
479 saved_box_initialize();
480 saved_box_slot = slot;
481 saved_box_context = context;
482
483 saved_box_packing = spec_packing;
484 saved_box_amount = spec_amount;
485
486 saved_box_direction = spec_direction;
487 if (spec_direction != direction_unknown) {
488 saved_box_dir_pointer = lmt_dir_state.text_dir_ptr;
489 lmt_dir_state.text_dir_ptr = tex_new_dir(normal_dir_subtype, spec_direction);
490 } else {
491 saved_box_dir_pointer = null;
492 }
493 saved_box_attr_list = attrlist;
494 saved_box_pack = just_pack;
495 saved_box_orientation = orientation;
496 saved_box_anchor = anchor;
497 saved_box_geometry = geometry;
498 saved_box_xoffset = xoffset;
499 saved_box_yoffset = yoffset;
500 saved_box_xmove = xmove;
501 saved_box_ymove = ymove;
502 saved_box_source = source;
503 saved_box_target = target;
504 saved_box_state = state;
505 saved_box_options = options;
506 saved_box_shift = shift;
507 saved_box_axis = axis;
508 saved_box_class = mainclass;
509 saved_box_retain = retain;
510 saved_box_callback = callback;
511 saved_box_leaders = leaders;
512 lmt_save_state.save_stack_data.ptr += saved_box_n_of_records;
513 tex_new_save_level(c);
514 if (! brace) {
515 tex_scan_left_brace();
516 }
517 update_tex_par_direction(spec_direction);
518 update_tex_text_direction(spec_direction);
519}
520
521
538
539packaging_state_info lmt_packaging_state = {
540 .total_stretch = { 0 },
541 .total_shrink = { 0 },
542 .last_badness = 0,
543 .last_overshoot = 0,
544 .post_adjust_tail = null,
545 .pre_adjust_tail = null,
546 .post_migrate_tail = null,
547 .pre_migrate_tail = null,
548 .last_leftmost_char = null,
549 .last_rightmost_char = null,
550 .pack_begin_line = 0,
551
552 .best_height_plus_depth = 0,
553 .previous_char_ptr = null,
554 .font_expansion_ratio = 0,
555 .except = 0,
556 .page_discards_tail = null,
557 .page_discards_head = null,
558 .split_discards_head = null,
559 .split_last_height = 0,
560 .split_last_depth = 0,
561 .split_last_stretch = 0,
562 .split_last_shrink = 0,
563};
564
565
601
602static inline int tex_has_glyph_expansion(halfword a)
603{
604 return
605 ! ((glyph_options(a) & glyph_option_no_expansion) == glyph_option_no_expansion)
606 && has_font_text_control(glyph_font(a), text_control_expansion);
607}
608
609scaled tex_char_stretch(halfword p)
610{
611 if (tex_has_glyph_expansion(p)) {
612 halfword m = lmt_font_state.adjust_stretch;
613 if (m > 0) {
614 halfword f = glyph_font(p);
615 halfword c = glyph_character(p);
616 scaled e = tex_char_ef_from_font(f, c);
617 if (e > 0) {
618 scaled dw = tex_calculated_glyph_width(p, m) - tex_char_width_from_glyph(p);
619 if (dw > 0) {
620 return tex_round_xn_over_d(dw, e, scaling_factor);
621 }
622 }
623 }
624 }
625 return 0;
626}
627
628scaled tex_char_shrink(halfword p)
629{
630 if (tex_has_glyph_expansion(p)) {
631 halfword m = lmt_font_state.adjust_shrink;
632 if (m > 0) {
633 halfword f = glyph_font(p);
634 halfword c = glyph_character(p);
635 scaled e = tex_char_cf_from_font(f, c);
636 if (e > 0) {
637 scaled dw = tex_char_width_from_glyph(p) - tex_calculated_glyph_width(p, -m);
638 if (dw > 0) {
639 return tex_round_xn_over_d(dw, e, scaling_factor);
640 }
641 }
642 }
643 }
644 return 0;
645}
646
647scaled tex_kern_stretch(halfword p)
648{
649 scaled w = kern_amount(p);
650 if (w) {
651 halfword l = lmt_packaging_state.previous_char_ptr;
652 if (l && node_type(l) == glyph_node && tex_has_glyph_expansion(l)) {
653 scaled m = lmt_font_state.adjust_stretch;
654 if (m > 0) {
655 scaled e = tex_char_ef_from_font(glyph_font(l), glyph_character(l));
656 if (e > 0) {
657 scaled dw = w - tex_round_xn_over_d(w, scaling_factor + m, scaling_factor);
658 if (dw > 0) {
659 return tex_round_xn_over_d(dw, e, scaling_factor);
660 }
661 }
662 }
663 }
664 }
665 return 0;
666}
667
668scaled tex_kern_shrink(halfword p)
669{
670 scaled w = kern_amount(p) ;
671 if (w) {
672 halfword l = lmt_packaging_state.previous_char_ptr;
673 if (l && node_type(l) == glyph_node && tex_has_glyph_expansion(l)) {
674 halfword m = lmt_font_state.adjust_shrink;
675 if (m > 0) {
676 scaled e = tex_char_cf_from_font(glyph_font(l), glyph_character(l));
677 if (e > 0) {
678 scaled dw = tex_round_xn_over_d(w, scaling_factor - m, scaling_factor) - w;
679 if (dw > 0) {
680 return tex_round_xn_over_d(dw, e, scaling_factor);
681 }
682 }
683 }
684 }
685 }
686 return 0;
687}
688
689
695
696static void tex_aux_set_kern_expansion(halfword p, halfword ratio)
697{
698 if (kern_amount(p)) {
699 halfword glyph = lmt_packaging_state.previous_char_ptr;
700 if (glyph && node_type(glyph) == glyph_node && tex_has_glyph_expansion(glyph)) {
701 halfword fnt = glyph_font(glyph);
702 halfword chr = glyph_character(glyph);
703 if (ratio > 0) {
704 scaled expansion = tex_char_ef_from_font(fnt, chr);
705 if (expansion > 0) {
706 halfword stretch = lmt_font_state.adjust_stretch;
707 if (stretch > 0) {
708 kern_expansion(p) = tex_ext_xn_over_d(ratio * expansion, stretch, scaling_factor);
709 }
710 }
711 } else if (ratio < 0) {
712 scaled compression = tex_char_cf_from_font(fnt, chr);
713 if (compression > 0) {
714 halfword shrink = lmt_font_state.adjust_shrink;
715 if (shrink > 0) {
716 kern_expansion(p) = tex_ext_xn_over_d(ratio * compression, shrink, scaling_factor);
717 }
718 }
719 } else {
720
721 }
722 }
723 }
724}
725
726static void tex_aux_set_glyph_expansion(halfword p, int ratio)
727{
728 switch (node_type(p)) {
729 case glyph_node:
730 if (tex_has_glyph_expansion(p)) {
731 if (ratio > 0) {
732 halfword fnt = glyph_font(p);
733 halfword chr = glyph_character(p);
734 scaled expansion = tex_char_ef_from_font(fnt, chr);
735 if (expansion > 0) {
736 halfword stretch = lmt_font_state.adjust_stretch;
737 if (stretch > 0) {
738 glyph_expansion(p) = tex_ext_xn_over_d(ratio * expansion, stretch, scaling_factor);
739 }
740 }
741 } else if (ratio < 0) {
742 halfword fnt = glyph_font(p);
743 halfword chr = glyph_character(p);
744 scaled compression = tex_char_cf_from_font(fnt, chr);
745 if (compression > 0) {
746 halfword shrink = lmt_font_state.adjust_shrink;
747 if (shrink > 0) {
748 glyph_expansion(p) = tex_ext_xn_over_d(ratio * compression, shrink, scaling_factor);
749 }
750 }
751 }
752 }
753 break;
754 case disc_node:
755 {
756 halfword r = disc_pre_break_head(p);
757 while (r) {
758 if (node_type(r) == glyph_node) {
759 tex_aux_set_glyph_expansion(r, ratio);
760 }
761 r = node_next(r);
762 }
763 r = disc_post_break_head(p);
764 while (r) {
765 if (node_type(r) == glyph_node) {
766 tex_aux_set_glyph_expansion(r, ratio);
767 }
768 r = node_next(r);
769 }
770 r = disc_no_break_head(p);
771 while (r) {
772 if (node_type(r) == glyph_node) {
773 tex_aux_set_glyph_expansion(r, ratio);
774 }
775 r = node_next(r);
776 }
777 break;
778 }
779 default:
780 tex_normal_error("font expansion", "invalid node type");
781 break;
782 }
783}
784
785scaled tex_left_marginkern(halfword p)
786{
787 while (p && node_type(p) == glue_node) {
788 p = node_next(p);
789 }
790 if (p && node_type(p) == kern_node && node_subtype(p) == left_margin_kern_subtype) {
791 return kern_amount(p);
792 } else {
793 return 0;
794 }
795}
796
797scaled tex_right_marginkern(halfword p)
798{
799 if (p) {
800 p = tex_tail_of_node_list(p);
801
805 while (p) {
806 switch(node_type(p)) {
807 case glue_node:
808
809 p = node_prev(p);
810 break;
811 case kern_node:
812 if (node_subtype(p) == right_margin_kern_subtype) {
813 return kern_amount(p);
814 } else {
815 return 0;
816 }
817 case disc_node:
818
823 p = node_prev(p);
824 if (p && node_type(p) == kern_node && node_subtype(p) == right_margin_kern_subtype) {
825 return kern_amount(p);
826 } else {
827 return 0;
828 }
829 default:
830 return 0;
831 }
832 }
833 }
834 return 0;
835}
836
837
843
844scaled tex_char_protrusion(halfword p, int side)
845{
846 if (side == left_margin_kern_subtype) {
847 lmt_packaging_state.last_leftmost_char = null;
848 } else {
849 lmt_packaging_state.last_rightmost_char = null;
850 }
851 if (! p || node_type(p) != glyph_node || tex_has_glyph_option(p, glyph_option_no_protrusion)) {
852 return 0;
853 } else if (side == left_margin_kern_subtype) {
854 lmt_packaging_state.last_leftmost_char = p;
855 return tex_char_left_protrusion_from_glyph(p);
856 } else {
857 lmt_packaging_state.last_rightmost_char = p;
858 return tex_char_right_protrusion_from_glyph(p);
859 }
860}
861
862
868
869int tex_ignore_math_skip(halfword p)
870{
871 if (math_skip_mode_par == math_skip_only_when_skip) {
872 if (node_subtype(p) == end_inline_math) {
873 if (tex_math_skip_boundary(node_next(p))) {
874 return 0;
875 }
876 } else {
877 if (tex_math_skip_boundary(node_prev(p))) {
878 return 0;
879 }
880 }
881 } else if (math_skip_mode_par == math_skip_only_when_no_skip) {
882 if (node_subtype(p) == end_inline_math) {
883 if (! tex_math_skip_boundary(node_next(p))) {
884 return 0;
885 }
886 } else {
887 if (! tex_math_skip_boundary(node_prev(p))) {
888 return 0;
889 }
890 }
891 } else {
892 return 0;
893 }
894 tex_reset_math_glue_to_zero(p);
895 return 1;
896}
897
898# define fix_int(val,min,max) (val < min ? min : (val > max ? max : val))
899
900static inline halfword tex_aux_used_order(halfword *total)
901{
902 if (total[filll_glue_order]) {
903 return filll_glue_order;
904 } else if (total[fill_glue_order]) {
905 return fill_glue_order;
906 } else if (total[fil_glue_order]) {
907 return fil_glue_order;
908 } else if (total[fi_glue_order]) {
909 return fi_glue_order;
910 } else {
911 return normal_glue_order;
912 }
913}
914
915
939
940
944
945static inline void tex_aux_promote_pre_migrated(halfword r, halfword p)
946{
947 halfword pa = box_pre_adjusted(p);
948 halfword pm = box_pre_migrated(p);
949 if (pa) {
950 if (lmt_packaging_state.pre_adjust_tail) {
951 lmt_packaging_state.pre_adjust_tail = tex_append_adjust_list(pre_adjust_head, lmt_packaging_state.pre_adjust_tail, pa, "promote");
952 } else if (box_pre_adjusted(r)) {
953 tex_couple_nodes(box_pre_adjusted(r), pa);
954 } else {
955 box_pre_adjusted(r) = pa;
956 }
957 box_pre_adjusted(p) = null;
958 }
959 if (pm) {
960 if (lmt_packaging_state.pre_migrate_tail) {
961 tex_couple_nodes(lmt_packaging_state.pre_migrate_tail, pm);
962 lmt_packaging_state.pre_migrate_tail = tex_tail_of_node_list(pm);
963 } else {
964
965 halfword rm = box_pre_migrated(r);
966 if (rm) {
967 tex_couple_nodes(pm, rm);
968 }
969 box_pre_migrated(r) = pm;
970 }
971 box_pre_migrated(p) = null;
972 }
973}
974
975static inline void tex_aux_promote_post_migrated(halfword r, halfword p)
976{
977 halfword pa = box_post_adjusted(p);
978 halfword pm = box_post_migrated(p);
979 if (pa) {
980 if (lmt_packaging_state.post_adjust_tail) {
981 lmt_packaging_state.post_adjust_tail = tex_append_adjust_list(post_adjust_head, lmt_packaging_state.post_adjust_tail, pa, "promote");
982 } else if (box_post_adjusted(r)) {
983 tex_couple_nodes(box_post_adjusted(r), pa);
984 } else {
985 box_post_adjusted(r) = pa;
986 }
987 box_post_adjusted(p) = null;
988 }
989 if (box_except(p)) {
990 lmt_packaging_state.except = box_except(p);
991 }
992 if (pm) {
993 if (lmt_packaging_state.post_migrate_tail) {
994 tex_couple_nodes(lmt_packaging_state.post_migrate_tail, pm);
995 lmt_packaging_state.post_migrate_tail = tex_tail_of_node_list(pm);
996 } else {
997
998 halfword rm = box_post_migrated(r);
999 if (rm) {
1000 tex_couple_nodes(tex_tail_of_node_list(rm), pm);
1001 } else {
1002 box_post_migrated(r) = pm;
1003 }
1004 }
1005 box_post_migrated(p) = null;
1006 }
1007}
1008
1009static inline halfword tex_aux_post_migrate(halfword r, halfword p)
1010{
1011 halfword n = p;
1012 halfword nn = node_next(p);
1013 halfword pm = box_post_migrated(r);
1014 if (p == box_list(r)) {
1015 box_list(r) = nn;
1016 if (nn) {
1017 node_prev(nn) = null;
1018 }
1019 } else {
1020 tex_couple_nodes(node_prev(p), nn);
1021 }
1022 if (pm) {
1023 tex_couple_nodes(tex_tail_of_node_list(pm), n);
1024 } else {
1025 box_post_migrated(r) = n;
1026 }
1027 node_next(n) = null;
1028 p = nn;
1029 return p;
1030}
1031
1032static inline halfword tex_aux_normal_migrate(halfword r, halfword p)
1033{
1034 halfword n = p;
1035 halfword nn = node_next(p);
1036 if (p == box_list(r)) {
1037 box_list(r) = nn;
1038 if (nn) {
1039 node_prev(nn) = null;
1040 }
1041 } else {
1042 tex_couple_nodes(node_prev(p), nn);
1043 }
1044 tex_couple_nodes(lmt_packaging_state.post_migrate_tail, n);
1045 lmt_packaging_state.post_migrate_tail = n;
1046 node_next(n) = null;
1047 p = nn;
1048 return p;
1049}
1050
1051static void tex_aux_append_diagnostic_rule(halfword box, halfword rule)
1052{
1053 halfword n = box_list(box);
1054 if (n) {
1055
1056 halfword t = tex_tail_of_node_list(n);
1057 halfword c = t;
1058 while (c && node_type(c) == glue_node) {
1059 switch (node_subtype(c)) {
1060 case par_fill_right_skip_glue:
1061 case par_init_right_skip_glue:
1062 case right_skip_glue:
1063 case right_hang_skip_glue:
1064 c = node_prev(c);
1065 break;
1066 default:
1067 goto DONE;
1068 }
1069 }
1070 DONE:
1071 if (c) {
1072 n = node_next(c);
1073 if (n) {
1074 tex_couple_nodes(rule, n);
1075 }
1076 } else {
1077 c = t;
1078 }
1079 tex_couple_nodes(c, rule);
1080 } else {
1081 box_list(box) = rule;
1082 }
1083}
1084
1085void tex_repack(halfword p, scaled w, int m)
1086{
1087 if (p) {
1088 halfword tmp;
1089 switch (node_type(p)) {
1090 case hlist_node:
1091 tmp = tex_hpack(box_list(p), w, m, box_dir(p), holding_none_option, box_limit_none);
1092 break;
1093 case vlist_node:
1094 tmp = tex_vpack(box_list(p), w, m > packing_additional ? packing_additional : m, max_dimension, box_dir(p), holding_none_option, NULL);
1095 break;
1096 default:
1097 return;
1098 }
1099 box_width(p) = box_width(tmp);
1100 box_height(p) = box_height(tmp);
1101 box_depth(p) = box_depth(tmp);
1102 box_glue_set(p) = box_glue_set(tmp);
1103 box_glue_order(p) = box_glue_order(tmp);
1104 box_glue_sign(p) = box_glue_sign(tmp);
1105 box_list(tmp) = null;
1106 tex_flush_node(tmp);
1107 }
1108}
1109
1110
1111
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1124
1125void tex_freeze(halfword p, int recurse, int limitate, halfword factor)
1126{
1127 if (p) {
1128 switch (node_type(p)) {
1129 case hlist_node:
1130 {
1131 halfword c = box_list(p);
1132 double set = (double) box_glue_set(p);
1133 halfword order = box_glue_order(p);
1134 singleword sign = box_glue_sign(p);
1135 if (factor > 0) {
1136 set *= factor * 0.001;
1137 } else if (factor < 0) {
1138 double max = - factor * 0.001;
1139 if (set > max) {
1140 set = max;
1141 }
1142 }
1143 while (c) {
1144 switch (node_type(c)) {
1145 case glue_node:
1146 switch (sign) {
1147 case stretching_glue_sign:
1148 if (glue_stretch_order(c) == order) {
1149 glue_amount(c) += limitate == hlist_node ? glue_stretch(c) : scaledround(glue_stretch(c) * set);
1150 }
1151 break;
1152 case shrinking_glue_sign:
1153 if (glue_shrink_order(c) == order) {
1154 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1155 }
1156 break;
1157 }
1158 glue_stretch(c) = 0;
1159 glue_shrink(c) = 0;
1160 glue_stretch_order(c) = 0;
1161 glue_shrink_order(c) = 0;
1162 break;
1163 case hlist_node:
1164 case vlist_node:
1165 if (recurse) {
1166 tex_freeze(c, recurse, limitate, factor);
1167 }
1168 break;
1169 case math_node:
1170 switch (sign) {
1171 case stretching_glue_sign:
1172 if (math_stretch_order(c) == order) {
1173 math_amount(c) += limitate == hlist_node ? math_stretch(c) : scaledround(math_stretch(c) * set);
1174 }
1175 break;
1176 case shrinking_glue_sign:
1177 if (math_shrink_order(c) == order) {
1178 math_amount(c) += scaledround(math_shrink(c) * set);
1179 }
1180 break;
1181 }
1182 math_stretch(c) = 0;
1183 math_shrink(c) = 0;
1184 math_stretch_order(c) = 0;
1185 math_shrink_order(c) = 0;
1186 break;
1187 default:
1188 break;
1189 }
1190 c = node_next(c);
1191 }
1192 box_glue_set(p) = 0;
1193 box_glue_order(p) = 0;
1194 box_glue_sign(p) = 0;
1195 }
1196 break;
1197 case vlist_node:
1198 {
1199 halfword c = box_list(p);
1200 double set = (double) box_glue_set(p);
1201 halfword order = box_glue_order(p);
1202 singleword sign = box_glue_sign(p);
1203 if (factor > 0) {
1204 set *= factor * 0.001;
1205 } else if (factor < 0) {
1206 double max = - factor * 0.001;
1207 if (set > max) {
1208 set = max;
1209 }
1210 }
1211 while (c) {
1212 switch (node_type(c)) {
1213 case glue_node:
1214 switch (sign) {
1215 case stretching_glue_sign:
1216 if (glue_stretch_order(c) == order) {
1217 glue_amount(c) += limitate == vlist_node ? glue_stretch(c) : scaledround(glue_stretch(c) * set);
1218 }
1219 break;
1220 case shrinking_glue_sign:
1221 if (glue_shrink_order(c) == order) {
1222 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1223 }
1224 break;
1225 }
1226 glue_stretch(c) = 0;
1227 glue_shrink(c) = 0;
1228 glue_stretch_order(c) = 0;
1229 glue_shrink_order(c) = 0;
1230 break;
1231 case hlist_node:
1232 case vlist_node:
1233 if (recurse) {
1234 tex_freeze(c, recurse, limitate, factor);
1235 }
1236 break;
1237 default:
1238 break;
1239 }
1240 c = node_next(c);
1241 }
1242 box_glue_set(p) = 0;
1243 box_glue_order(p) = 0;
1244 box_glue_sign(p) = 0;
1245 }
1246 break;
1247 default:
1248 return;
1249 }
1250 }
1251}
1252
1253static inline halfword tex_aux_migrate_decouple(halfword head, halfword current, halfword next, halfword *first, halfword *last)
1254{
1255 halfword prev = node_prev(current);
1256 tex_uncouple_node(current);
1257 if (current == head) {
1258 node_prev(next) = null;
1259 head = next;
1260 } else {
1261 tex_try_couple_nodes(prev, next);
1262 }
1263 if (*first) {
1264 tex_couple_nodes(*last, current);
1265 } else {
1266 *first = current;
1267 }
1268 *last = current;
1269 return head;
1270}
1271
1272static halfword tex_aux_migrate_locate(halfword head, halfword *first, halfword *last, int inserts, int marks)
1273{
1274 halfword current = head;
1275 while (current) {
1276 halfword next = node_next(current);
1277 switch (node_type(current)) {
1278 case vlist_node:
1279 case hlist_node:
1280 {
1281 halfword list = box_list(current);
1282 if (list) {
1283 box_list(current) = tex_aux_migrate_locate(list, first, last, inserts, marks);
1284 }
1285 break;
1286 }
1287 case insert_node:
1288 {
1289 if (inserts) {
1290 halfword list;
1291 head = tex_aux_migrate_decouple(head, current, next, first, last);
1292 list = insert_list(current);
1293 if (list) {
1294 insert_list(current) = tex_aux_migrate_locate(list, first, last, inserts, marks);
1295 }
1296 }
1297 break;
1298 }
1299 case mark_node:
1300 {
1301 if (marks) {
1302 head = tex_aux_migrate_decouple(head, current, next, first, last);
1303 }
1304 break;
1305 }
1306 default:
1307 break;
1308 }
1309 current = next;
1310 }
1311 return head;
1312}
1313
1314void tex_migrate(halfword head, halfword *first, halfword *last, int inserts, int marks)
1315{
1316 if (head) {
1317 halfword current = head;
1318 while (current) {
1319 switch (node_type(current)) {
1320 case hlist_node:
1321 case vlist_node:
1322 {
1323 halfword list = box_list(current);
1324 if (list) {
1325 box_list(current) = tex_aux_migrate_locate(list, first, last, inserts, marks);
1326 }
1327 break;
1328 }
1329 case insert_node:
1330 if (inserts) {
1331 halfword list = insert_list(current);
1332 if (list) {
1333 insert_list(current) = tex_aux_migrate_locate(list, first, last, inserts, marks);
1334 }
1335 break;
1336 }
1337 }
1338 current = node_next(current);
1339 }
1340 }
1341}
1342
1343void tex_limit(halfword p)
1344{
1345
1349 if (p) {
1350 halfword c = box_list(p);
1351 double set = (double) box_glue_set(p);
1352 halfword order = box_glue_order(p);
1353 singleword sign = box_glue_sign(p);
1354 int limit = set > 1.0 && order == normal_glue_order;
1355 if (limit) {
1356 long long nonfrozen = 0;
1357 long long frozen = 0;
1358 while (c) {
1359 if (node_type(c) == glue_node) {
1360 switch (sign) {
1361 case stretching_glue_sign:
1362 if (glue_stretch_order(c) == order) {
1363 if (tex_has_glue_option(c, glue_option_limit)) {
1364 frozen += glue_stretch(c);
1365 } else {
1366 nonfrozen += glue_stretch(c);
1367 }
1368 }
1369 break;
1370 case shrinking_glue_sign:
1371 if (glue_shrink_order(c) == order) {
1372 if (tex_has_glue_option(c, glue_option_limit)) {
1373 frozen -= glue_shrink(c);
1374 } else {
1375 nonfrozen -= glue_shrink(c);
1376 }
1377 }
1378 break;
1379 }
1380 }
1381 c = node_next(c);
1382 }
1383 if (nonfrozen) {
1384 set = (double) (set * (frozen + nonfrozen) - frozen) / (double) nonfrozen;
1385 } else {
1386 limit = 0;
1387 }
1388 }
1389 c = box_list(p);
1390 while (c) {
1391 if (node_type(c) == glue_node) {
1392 switch (sign) {
1393 case stretching_glue_sign:
1394 if (glue_stretch_order(c) == order) {
1395 if (limit && tex_has_glue_option(c, glue_option_limit)) {
1396 glue_amount(c) += glue_stretch(c);
1397 } else {
1398 glue_amount(c) += scaledround(glue_stretch(c) * set);
1399 }
1400 }
1401 break;
1402 case shrinking_glue_sign:
1403 if (glue_shrink_order(c) == order) {
1404 if (limit && tex_has_glue_option(c, glue_option_limit)) {
1405 glue_amount(c) -= glue_shrink(c);
1406 } else {
1407 glue_amount(c) -= scaledround(glue_shrink(c) * set);
1408 }
1409 }
1410 break;
1411 }
1412 glue_stretch(c) = 0;
1413 glue_shrink(c) = 0;
1414 glue_stretch_order(c) = 0;
1415 glue_shrink_order(c) = 0;
1416 }
1417 c = node_next(c);
1418 }
1419 box_glue_set(p) = 0;
1420 box_glue_order(p) = 0;
1421 box_glue_sign(p) = 0;
1422 }
1423}
1424
1425scaled tex_stretch(halfword p)
1426{
1427 scaled stretch = 0;
1428 if (p) {
1429 switch (node_type(p)) {
1430 case hlist_node:
1431 case vlist_node:
1432 if (box_glue_sign(p) == stretching_glue_sign) {
1433 halfword c = box_list(p);
1434 halfword order = box_glue_order(p);
1435 while (c) {
1436 switch (node_type(c)) {
1437 case glue_node:
1438 if (glue_stretch_order(c) == order) {
1439 stretch += glue_stretch(c);
1440 }
1441 break;
1442 case math_node:
1443 if (math_stretch_order(c) == order) {
1444 stretch += math_stretch(c);
1445 }
1446 break;
1447 }
1448 c = node_next(c);
1449 }
1450 }
1451 break;
1452 }
1453 }
1454 return stretch;
1455}
1456
1457scaled tex_shrink(halfword p)
1458{
1459 scaled shrink = 0;
1460 if (p) {
1461 switch (node_type(p)) {
1462 case hlist_node:
1463 case vlist_node:
1464 if (box_glue_sign(p) == shrinking_glue_sign) {
1465 halfword c = box_list(p);
1466 halfword order = box_glue_order(p);
1467 while (c) {
1468 switch (node_type(c)) {
1469 case glue_node:
1470 if (glue_shrink_order(c) == order) {
1471 shrink += glue_shrink(c);
1472 }
1473 break;
1474 case math_node:
1475 if (math_shrink_order(c) == order) {
1476 shrink += math_shrink(c);
1477 }
1478 break;
1479 }
1480 c = node_next(c);
1481 }
1482 }
1483 break;
1484 }
1485 }
1486 return shrink;
1487}
1488
1489halfword tex_hpack(halfword p, scaled target, int method, singleword pack_direction, int retain, int limit)
1490{
1491 halfword tail = null;
1492 scaled height = 0;
1493 scaled depth = 0;
1494 scaled width = 0;
1495 scaled excess = 0;
1496 singleword hpack_dir = pack_direction == direction_unknown ?(singleword) text_direction_par : pack_direction;
1497 int disc_level = 0;
1498 int has_uleader = 0;
1499 halfword pack_interrupt[8];
1500 scaled font_stretch = 0;
1501 scaled font_shrink = 0;
1502 int adjust_spacing = adjust_spacing_off;
1503 int has_limit = box_limit_mode_hlist ? 1 : (limit == box_limit_line && box_limit_mode_line ? 1 : -1);
1504
1505 halfword result = tex_new_node(hlist_node, unknown_list);
1506 box_dir(result) = hpack_dir;
1507 lmt_packaging_state.last_badness = 0;
1508 lmt_packaging_state.last_overshoot = 0;
1509 switch(method) {
1510 case packing_linebreak:
1511 method = packing_expanded;
1512
1513 case packing_substitute:
1514 adjust_spacing = tex_checked_font_adjust(
1515 lmt_linebreak_state.adjust_spacing,
1516 lmt_linebreak_state.adjust_spacing_step,
1517 lmt_linebreak_state.adjust_spacing_shrink,
1518 lmt_linebreak_state.adjust_spacing_stretch
1519 );
1520 break;
1521 default:
1522 adjust_spacing = tex_checked_font_adjust(
1523 adjust_spacing_par,
1524 adjust_spacing_step_par,
1525 adjust_spacing_shrink_par,
1526 adjust_spacing_stretch_par
1527 );
1528 break;
1529 }
1530 box_list(result) = p;
1531 switch (method) {
1532 case packing_expanded:
1533
1534 lmt_packaging_state.previous_char_ptr = null;
1535 break;
1536 case packing_adapted:
1537 if (target > scaling_factor) {
1538 target = scaling_factor;
1539 } else if (target < -scaling_factor) {
1540 target = -scaling_factor;
1541 }
1542 }
1543 for (int i = normal_glue_order; i <= filll_glue_order; i++) {
1544 lmt_packaging_state.total_stretch[i] = 0;
1545 lmt_packaging_state.total_shrink[i] = 0;
1546 }
1547
1560 while (p) {
1561 switch (node_type(p)) {
1562 case glyph_node:
1563 {
1564 scaledwhd whd;
1565 if (adjust_spacing) {
1566 switch (method) {
1567 case packing_expanded:
1568 {
1569 lmt_packaging_state.previous_char_ptr = p;
1570 font_stretch += tex_char_stretch(p);
1571 font_shrink += tex_char_shrink(p);
1572 break;
1573 }
1574 case packing_substitute:
1575 lmt_packaging_state.previous_char_ptr = p;
1576 if (lmt_packaging_state.font_expansion_ratio != 0) {
1577 tex_aux_set_glyph_expansion(p, lmt_packaging_state.font_expansion_ratio);
1578 }
1579 break;
1580 }
1581 }
1582 whd = tex_glyph_dimensions_ex(p);
1583 width += whd.wd;
1584 if (whd.ht > height) {
1585 height = whd.ht;
1586 }
1587 if (whd.dp > depth) {
1588 depth = whd.dp;
1589 }
1590 break;
1591 }
1592 case hlist_node:
1593 case vlist_node:
1594 {
1595
1601 halfword shift = box_shift_amount(p);
1602 scaledwhd whd = tex_pack_dimensions(p);
1603 width += whd.wd;
1604 if (whd.ht - shift > height) {
1605 height = whd.ht - shift;
1606 }
1607 if (whd.dp + shift > depth) {
1608 depth = whd.dp + shift;
1609 }
1610 tex_aux_promote_pre_migrated(result, p);
1611 tex_aux_promote_post_migrated(result, p);
1612 break;
1613 }
1614 case unset_node:
1615 width += box_width(p);
1616 if (box_height(p) > height) {
1617 height = box_height(p);
1618 }
1619 if (box_depth(p) > depth) {
1620 depth = box_depth(p);
1621 }
1622
1623 break;
1624 case rule_node:
1625
1632 width += rule_width(p);
1633 if (rule_height(p) > height) {
1634 height = rule_height(p);
1635 }
1636 if (rule_depth(p) > depth) {
1637 depth = rule_depth(p);
1638 }
1639 break;
1640 case glue_node:
1641
1642 {
1643 switch (method) {
1644 case packing_adapted:
1645 if (target < 0) {
1646 if (glue_shrink_order(p) == normal_glue_order) {
1647 glue_amount(p) -= scaledround(-0.001 * target * (double) glue_shrink(p));
1648 }
1649 } else if (target > 0) {
1650 if (glue_stretch_order(p) == normal_glue_order) {
1651 glue_amount(p) += scaledround( 0.001 * target * (double) glue_stretch(p));
1652 }
1653 }
1654 width += glue_amount(p);
1655 glue_shrink_order(p) = normal_glue_order;
1656 glue_shrink(p) = 0;
1657 glue_stretch_order(p) = normal_glue_order;
1658 glue_stretch(p) = 0;
1659 break;
1660 default:
1661 width += glue_amount(p);
1662 lmt_packaging_state.total_stretch[glue_stretch_order(p)] += glue_stretch(p);
1663 lmt_packaging_state.total_shrink[glue_shrink_order(p)] += glue_shrink(p);
1664 }
1665 if (is_leader(p)) {
1666 halfword gl = glue_leader_ptr(p);
1667 scaled ht = 0;
1668 scaled dp = 0;
1669 switch (node_type(gl)) {
1670 case hlist_node:
1671 case vlist_node:
1672 ht = box_height(gl);
1673 dp = box_depth(gl);
1674 break;
1675 case rule_node:
1676 ht = rule_height(gl);
1677 dp = rule_depth(gl);
1678 break;
1679
1680 }
1681 if (ht > height) {
1682 height = ht;
1683 }
1684 if (dp > depth) {
1685 depth = dp;
1686 }
1687 if (node_subtype(p) == u_leaders) {
1688 has_uleader = 1;
1689 }
1690 }
1691 if (! has_limit && tex_has_glue_option(p, glue_option_limit)) {
1692 has_limit = 1;
1693 }
1694 break;
1695 }
1696 case kern_node:
1697 if (adjust_spacing == adjust_spacing_full && node_subtype(p) == font_kern_subtype) {
1698 switch (method) {
1699 case packing_expanded:
1700 {
1701 font_stretch += tex_kern_stretch(p);
1702 font_shrink += tex_kern_shrink(p);
1703 break;
1704 }
1705 case packing_substitute:
1706 if (lmt_packaging_state.font_expansion_ratio != 0) {
1707 tex_aux_set_kern_expansion(p, lmt_packaging_state.font_expansion_ratio);
1708 }
1709 break;
1710 }
1711 }
1712 width += tex_kern_dimension_ex(p);
1713 break;
1714 case disc_node:
1715 if (adjust_spacing) {
1716 switch (method) {
1717 case packing_expanded:
1718
1722 break;
1723 case packing_substitute:
1724 if (lmt_packaging_state.font_expansion_ratio != 0) {
1725 tex_aux_set_glyph_expansion(p, lmt_packaging_state.font_expansion_ratio);
1726 }
1727 break;
1728 }
1729 }
1730 if (disc_no_break_head(p)) {
1731 pack_interrupt[disc_level] = node_next(p);
1732 ++disc_level;
1733 p = disc_no_break(p);
1734 }
1735 break;
1736 case math_node:
1737 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
1738 width += math_surround(p);
1739 } else {
1740 width += math_amount(p);
1741 lmt_packaging_state.total_stretch[math_stretch_order(p)] += math_stretch(p);
1742 lmt_packaging_state.total_shrink[math_shrink_order(p)] += math_shrink(p);
1743 }
1744 break;
1745 case dir_node:
1746 break;
1747 case insert_node:
1748 if (retain_inserts(retain)) {
1749 break;
1750 } else if (lmt_packaging_state.post_migrate_tail) {
1751 p = tex_aux_normal_migrate(result, p);
1752
1753 continue;
1754 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_insert)) {
1755 halfword l = insert_list(p);
1756 p = tex_aux_post_migrate(result, p);
1757 while (l) {
1758 l = node_type(l) == insert_node ? tex_aux_post_migrate(result, l) : node_next(l);
1759 }
1760
1761 continue;
1762 } else {
1763
1764 break;
1765 }
1766 case mark_node:
1767 if (retain_marks(retain)) {
1768 break;
1769 } else if (lmt_packaging_state.post_migrate_tail) {
1770 p = tex_aux_normal_migrate(result, p);
1771
1772 continue;
1773 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_mark)) {
1774 p = tex_aux_post_migrate(result, p);
1775
1776 continue;
1777 } else {
1778
1779 break;
1780 }
1781 case adjust_node:
1782
1786 if (adjust_list(p) && ! retain_adjusts(retain)) {
1787 halfword next = node_next(p);
1788 halfword current = p;
1789
1790 if (p == box_list(result)) {
1791 box_list(result) = next;
1792 if (next) {
1793 node_prev(next) = null;
1794 }
1795 } else {
1796 tex_couple_nodes(node_prev(p), next);
1797 }
1798 if (lmt_packaging_state.post_adjust_tail || lmt_packaging_state.pre_adjust_tail) {
1799 tex_adjust_passon(result, current);
1800 } else if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_adjust)) {
1801 tex_adjust_attach(result, current);
1802 }
1803 p = next;
1804 continue;
1805 } else {
1806 break;
1807 }
1808 default:
1809 break;
1810 }
1811
1816 if (disc_level > 0) {
1817 p = node_next(p);
1818 if (! p) {
1819 --disc_level;
1820 p = pack_interrupt[disc_level];
1821 }
1822 } else {
1823 tail = p;
1824 p = node_next(p);
1825 }
1826 }
1827 box_height(result) = height;
1828 box_depth(result) = depth;
1829
1834 switch (method) {
1835 case packing_additional:
1836 target += width;
1837 break;
1838 case packing_adapted:
1839 target = width;
1840 break;
1841 }
1842 box_width(result) = target;
1843 excess = target - width;
1844 if (excess == 0) {
1845 box_glue_sign(result) = normal_glue_sign;
1846 box_glue_order(result) = normal_glue_order;
1847 box_glue_set(result) = 0.0;
1848 goto EXIT;
1849 } else if (excess > 0) {
1850
1855 halfword order = tex_aux_used_order(lmt_packaging_state.total_stretch);
1856 if ((method == packing_expanded) && (order == normal_glue_order) && (font_stretch > 0)) {
1857 lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(excess, font_stretch, scaling_factor_double);
1858 goto EXIT;
1859 }
1860 box_glue_order(result) = order;
1861 box_glue_sign(result) = stretching_glue_sign;
1862 if (lmt_packaging_state.total_stretch[order]) {
1863 box_glue_set(result) = (glueratio) ((double) excess / lmt_packaging_state.total_stretch[order]);
1864 } else {
1865
1866 box_glue_sign(result) = normal_glue_sign;
1867 box_glue_set(result) = 0.0;
1868 }
1869 if (order == normal_glue_order && box_list(result)) {
1870
1873 lmt_packaging_state.last_badness = tex_badness(excess, lmt_packaging_state.total_stretch[normal_glue_order]);
1874 if (lmt_packaging_state.last_badness > hbadness_par) {
1875 int what = badness_mode_nothing;
1876 if (hbadness_mode_par & badness_mode_loose) {
1877 what = badness_mode_loose;
1878 } else if ((hbadness_mode_par & badness_mode_underfull) && (lmt_packaging_state.last_badness > 100)) {
1879 what = badness_mode_underfull;
1880 }
1881 if (what != badness_mode_nothing) {
1882 int callback_id = lmt_callback_defined(hpack_quality_callback);
1883 const char *verdict = what == badness_mode_underfull ? "underfull" : "loose";
1884 if (callback_id > 0) {
1885 if (tail) {
1886 halfword rule = null;
1887 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1888 verdict,
1889 lmt_packaging_state.last_badness,
1890 result,
1891 abs(lmt_packaging_state.pack_begin_line),
1892 lmt_input_state.input_line,
1893 tex_current_input_file_name(),
1894 &rule
1895 );
1896 if (rule && rule != result) {
1897 tex_aux_append_diagnostic_rule(result, rule);
1898 }
1899 }
1900 } else {
1901 tex_print_nlp();
1902 tex_print_format(
1903 "%l[package: %s \\hbox (badness %i)",
1904 verdict,
1905 lmt_packaging_state.last_badness
1906 );
1907 goto COMMON_ENDING;
1908 }
1909 }
1910 }
1911 }
1912 goto EXIT;
1913 } else {
1914
1917 halfword order = tex_aux_used_order(lmt_packaging_state.total_shrink);
1918 if ((method == packing_expanded) && (order == normal_glue_order) && (font_shrink > 0)) {
1919 lmt_packaging_state.font_expansion_ratio = tex_divide_scaled_n(excess, font_shrink, scaling_factor_double);
1920 goto EXIT;
1921 }
1922 box_glue_order(result) = order;
1923 box_glue_sign(result) = shrinking_glue_sign;
1924 if (lmt_packaging_state.total_shrink[order]) {
1925 box_glue_set(result) = (glueratio) ((double) (-excess) / (double) lmt_packaging_state.total_shrink[order]);
1926 } else {
1927
1928 box_glue_sign(result) = normal_glue_sign;
1929 box_glue_set(result) = 0.0;
1930 }
1931 if (order == normal_glue_order && box_list(result)) {
1932 if (lmt_packaging_state.total_shrink[order] < -excess) {
1933 int overshoot = -excess - lmt_packaging_state.total_shrink[normal_glue_order];
1934 lmt_packaging_state.last_badness = scaling_factor_squared;
1935 lmt_packaging_state.last_overshoot = overshoot;
1936
1937 box_glue_set(result) = 1.0;
1938
1939 if (((overshoot > hfuzz_par) || (hbadness_par < 100)) && (hbadness_mode_par & badness_mode_overfull)) {
1940 int callback_id = lmt_callback_defined(hpack_quality_callback);
1941 halfword rule = null;
1942 if (callback_id > 0) {
1943 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1944 "overfull",
1945 overshoot,
1946 result,
1947 abs(lmt_packaging_state.pack_begin_line),
1948 lmt_input_state.input_line,
1949 tex_current_input_file_name(),
1950 &rule);
1951 } else if (tail && overfull_rule_par > 0) {
1952 rule = tex_new_rule_node(normal_rule_subtype);
1953 rule_width(rule) = overfull_rule_par;
1954 }
1955 if (rule && rule != result) {
1956 tex_aux_append_diagnostic_rule(result, rule);
1957 }
1958 if (callback_id == 0) {
1959 tex_print_nlp();
1960 tex_print_format("%l[package: overfull \\hbox (%p too wide)", overshoot);
1961 goto COMMON_ENDING;
1962 }
1963 }
1964 } else {
1965
1966 lmt_packaging_state.last_badness = tex_badness(-excess, lmt_packaging_state.total_shrink[normal_glue_order]);
1967 if (lmt_packaging_state.last_badness > hbadness_par && (hbadness_mode_par & badness_mode_tight)) {
1968 int callback_id = lmt_callback_defined(hpack_quality_callback);
1969 if (callback_id > 0) {
1970 halfword rule = null;
1971 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->N",
1972 "tight",
1973 lmt_packaging_state.last_badness,
1974 result,
1975 abs(lmt_packaging_state.pack_begin_line),
1976 lmt_input_state.input_line,
1977 tex_current_input_file_name(),
1978 &rule);
1979 if (rule && rule != result) {
1980 tex_aux_append_diagnostic_rule(result, rule);
1981 }
1982 } else {
1983 tex_print_nlp();
1984 tex_print_format("%l[package: tight \\hbox (badness %i)", lmt_packaging_state.last_badness);
1985 goto COMMON_ENDING;
1986 }
1987 }
1988 }
1989 }
1990 goto EXIT;
1991 }
1992 COMMON_ENDING:
1993
1994 if (lmt_page_builder_state.output_active) {
1995 tex_print_format(" has occurred while \\output is active]");
1996 } else if (lmt_packaging_state.pack_begin_line == 0) {
1997 tex_print_format(" detected at line %i]", lmt_input_state.input_line);
1998 } else if (lmt_packaging_state.pack_begin_line > 0) {
1999 tex_print_format(" in paragraph at lines %i--%i]", lmt_packaging_state.pack_begin_line, lmt_input_state.input_line);
2000 } else {
2001 tex_print_format(" in alignment at lines %i--%i]", -lmt_packaging_state.pack_begin_line, lmt_input_state.input_line);
2002 }
2003 tex_print_ln();
2004 lmt_print_state.font_in_short_display = null_font;
2005 if (tracing_full_boxes_par > 0) {
2006 halfword detail = show_node_details_par;
2007 show_node_details_par = tracing_full_boxes_par;
2008 tex_print_str("%l[package: result] ");
2009 tex_short_display(box_list(result));
2010 tex_print_ln();
2011 tex_begin_diagnostic();
2012 tex_show_box(result);
2013 tex_end_diagnostic();
2014 show_node_details_par = detail;
2015 }
2016 EXIT:
2017 if ((method == packing_expanded) && (lmt_packaging_state.font_expansion_ratio != 0)) {
2018 halfword list = box_list(result);
2019 box_list(result) = null;
2020 tex_flush_node(result);
2021 lmt_packaging_state.font_expansion_ratio = fix_int(lmt_packaging_state.font_expansion_ratio, -scaling_factor, scaling_factor);
2022
2023 result = tex_hpack(list, target, packing_substitute, hpack_dir, holding_none_option, box_limit_none);
2024 } else {
2025 if (has_uleader) {
2026 set_box_package_state(result, package_u_leader_found);
2027 }
2028 if (has_limit > 0) {
2029 tex_limit(result);
2030 }
2031 }
2032
2033 lmt_packaging_state.font_expansion_ratio = 0;
2034 return result;
2035}
2036
2037halfword tex_filtered_hpack(halfword p, halfword qt, scaled w, int m, int grp, halfword d, int just_pack, halfword attr, int state, int retain)
2038{
2039 halfword head;
2040 singleword direction = (singleword) checked_direction_value(d);
2041 if (just_pack) {
2042 head = node_next(p);
2043 } else if (node_type(p) == temp_node && ! node_next(p)) {
2044 head = node_next(p);
2045 } else {
2046
2047 head = node_next(p);
2048 if (head) {
2049 node_prev(head) = null;
2050 if (tex_list_has_glyph(head)) {
2051 tex_handle_hyphenation(head, qt);
2052 head = tex_handle_glyphrun(head, grp, direction);
2053 }
2054 if (head) {
2055
2056 head = lmt_hpack_filter_callback(head, w, m, grp, direction, attr);
2057 }
2058 }
2059 }
2060 head = tex_hpack(head, w, m, direction, retain, box_limit_none);
2061 if (has_box_package_state(head, package_u_leader_found)) {
2062 if (head && normalize_line_mode_option(flatten_h_leaders_mode)) {
2063 if (! is_box_package_state(state, package_u_leader_delayed)) {
2064 tex_flatten_leaders(head, grp, just_pack, uleader_filtered_hpack, 0);
2065 }
2066 }
2067 }
2068 return head;
2069}
2070
2071
2072
2073scaledwhd tex_natural_hsizes(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order)
2074{
2075 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
2076 scaled gp = 0;
2077 scaled gm = 0;
2078 while (p && p != pp) {
2079 switch (node_type(p)) {
2080 case glyph_node:
2081 {
2082 scaledwhd whd = tex_glyph_dimensions_ex(p);
2083 siz.wd += whd.wd;
2084 if (whd.ht > siz.ht) {
2085 siz.ht = whd.ht;
2086 }
2087 if (whd.dp > siz.dp) {
2088 siz.dp = whd.dp;
2089 }
2090 break;
2091 }
2092 case hlist_node:
2093 case vlist_node:
2094 {
2095 scaled s = box_shift_amount(p);
2096 scaledwhd whd = tex_pack_dimensions(p);
2097 siz.wd += whd.wd;
2098 if (whd.ht - s > siz.ht) {
2099 siz.ht = whd.ht - s;
2100 }
2101 if (whd.dp + s > siz.dp) {
2102 siz.dp = whd.dp + s;
2103 }
2104 break;
2105 }
2106 case unset_node:
2107 siz.wd += box_width(p);
2108 if (box_height(p) > siz.ht) {
2109 siz.ht = box_height(p);
2110 }
2111 if (box_depth(p) > siz.dp) {
2112 siz.dp = box_depth(p);
2113 }
2114 break;
2115 case rule_node:
2116 siz.wd += rule_width(p);
2117 if (rule_height(p) > siz.ht) {
2118 siz.ht = rule_height(p);
2119 }
2120 if (rule_depth(p) > siz.dp) {
2121 siz.dp = rule_depth(p);
2122 }
2123 break;
2124 case glue_node:
2125 siz.wd += glue_amount(p);
2126 switch (g_sign) {
2127 case stretching_glue_sign:
2128 if (glue_stretch_order(p) == g_order) {
2129 gp += glue_stretch(p);
2130 }
2131 break;
2132 case shrinking_glue_sign:
2133 if (glue_shrink_order(p) == g_order) {
2134 gm += glue_shrink(p);
2135 }
2136 break;
2137 }
2138 if (is_leader(p)) {
2139 halfword gl = glue_leader_ptr(p);
2140 halfword ht = 0;
2141 halfword dp = 0;
2142 switch (node_type(gl)) {
2143 case hlist_node:
2144 case vlist_node:
2145 ht = box_height(gl);
2146 dp = box_depth(gl);
2147 break;
2148 case rule_node:
2149 ht = rule_height(gl);
2150 dp = rule_depth(gl);
2151 break;
2152
2153 }
2154 if (ht) {
2155 siz.ht = ht;
2156 }
2157 if (dp > siz.dp) {
2158 siz.dp = dp;
2159 }
2160 }
2161 break;
2162 case kern_node:
2163 siz.wd += tex_kern_dimension_ex(p);
2164 break;
2165 case disc_node:
2166 {
2167 scaledwhd whd = tex_natural_hsizes(disc_no_break_head(p), null, g_mult, g_sign, g_order);
2168 siz.wd += whd.wd;
2169 if (whd.ht > siz.ht) {
2170 siz.ht = whd.ht;
2171 }
2172 if (whd.dp > siz.dp) {
2173 siz.dp = whd.dp;
2174 }
2175 }
2176 break;
2177 case math_node:
2178 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2179 siz.wd += math_surround(p);
2180 } else {
2181 siz.wd += math_amount(p);
2182 switch (g_sign) {
2183 case stretching_glue_sign:
2184 if (math_stretch_order(p) == g_order) {
2185 gp += math_stretch(p);
2186 }
2187 break;
2188 case shrinking_glue_sign:
2189 if (math_shrink_order(p) == g_order) {
2190 gm += math_shrink(p);
2191 }
2192 break;
2193 }
2194 }
2195 break;
2196 case sub_box_node:
2197
2198 break;
2199 case sub_mlist_node:
2200 {
2201
2202 scaledwhd whd = tex_natural_hsizes(kernel_math_list(p), null, normal_glue_multiplier, normal_glue_sign, normal_glue_sign);
2203 siz.wd += whd.wd;
2204 if (whd.ht > siz.ht) {
2205 siz.ht = whd.ht;
2206 }
2207 if (whd.dp > siz.dp) {
2208 siz.dp = whd.dp;
2209 }
2210 }
2211 break;
2212 default:
2213 break;
2214 }
2215 p = node_next(p);
2216 }
2217 siz.ns = siz.wd;
2218 switch (g_sign) {
2219 case stretching_glue_sign:
2220 siz.wd += glueround((glueratio)(g_mult) * (glueratio)(gp));
2221 break;
2222 case shrinking_glue_sign:
2223 siz.wd -= glueround((glueratio)(g_mult) * (glueratio)(gm));
2224 break;
2225 }
2226 return siz;
2227}
2228
2229scaledwhd tex_natural_msizes(halfword p, int ignoreprime)
2230{
2231 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
2232 while (p) {
2233 switch (node_type(p)) {
2234 case glyph_node:
2235 {
2236 scaledwhd whd = tex_glyph_dimensions_ex(p);
2237 siz.wd += whd.wd;
2238 if (whd.ht > siz.ht) {
2239 siz.ht = whd.ht;
2240 }
2241 if (whd.dp > siz.dp) {
2242 siz.dp = whd.dp;
2243 }
2244 break;
2245 }
2246 case hlist_node:
2247 case vlist_node:
2248 {
2249 scaled s = box_shift_amount(p);
2250 scaledwhd whd = ignoreprime ? tex_natural_msizes(box_list(p), ignoreprime) : tex_pack_dimensions(p);
2251 siz.wd += whd.wd;
2252 if (ignoreprime) {
2253 switch (node_subtype(p)) {
2254 case math_prime_list:
2255 case math_sup_list:
2256 case math_scripts_list:
2257 goto HERE;
2258 }
2259 }
2260 if (whd.ht - s > siz.ht) {
2261 siz.ht = whd.ht - s;
2262 }
2263 HERE:
2264 if (whd.dp + s > siz.dp) {
2265 siz.dp = whd.dp + s;
2266 }
2267 break;
2268 }
2269 case unset_node:
2270 siz.wd += box_width(p);
2271 if (box_height(p) > siz.ht) {
2272 siz.ht = box_height(p);
2273 }
2274 if (box_depth(p) > siz.dp) {
2275 siz.dp = box_depth(p);
2276 }
2277 break;
2278 case rule_node:
2279 siz.wd += rule_width(p);
2280 if (rule_height(p) > siz.ht) {
2281 siz.ht = rule_height(p);
2282 }
2283 if (rule_depth(p) > siz.dp) {
2284 siz.dp = rule_depth(p);
2285 }
2286 break;
2287 case glue_node:
2288 siz.wd += glue_amount(p);
2289 if (is_leader(p)) {
2290 halfword gl = glue_leader_ptr(p);
2291 halfword ht = 0;
2292 halfword dp = 0;
2293 switch (node_type(gl)) {
2294 case hlist_node:
2295 case vlist_node:
2296 ht = box_height(gl);
2297 dp = box_depth(gl);
2298 break;
2299 case rule_node:
2300 ht = rule_height(gl);
2301 dp = rule_depth(gl);
2302 break;
2303
2304 }
2305 if (ht) {
2306 siz.ht = ht;
2307 }
2308 if (dp > siz.dp) {
2309 siz.dp = dp;
2310 }
2311 }
2312 break;
2313 case kern_node:
2314 siz.wd += tex_kern_dimension_ex(p);
2315 break;
2316 case disc_node:
2317 {
2318 scaledwhd whd = tex_natural_msizes(disc_no_break_head(p), ignoreprime);
2319 siz.wd += whd.wd;
2320 if (whd.ht > siz.ht) {
2321 siz.ht = whd.ht;
2322 }
2323 if (whd.dp > siz.dp) {
2324 siz.dp = whd.dp;
2325 }
2326 }
2327 break;
2328 case math_node:
2329 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2330 siz.wd += math_surround(p);
2331 } else {
2332 siz.wd += math_amount(p);
2333 }
2334 break;
2335 case sub_box_node:
2336 break;
2337 case sub_mlist_node:
2338 {
2339 scaledwhd whd = tex_natural_msizes(kernel_math_list(p), ignoreprime);
2340 siz.wd += whd.wd;
2341 if (whd.ht > siz.ht) {
2342 siz.ht = whd.ht;
2343 }
2344 if (whd.dp > siz.dp) {
2345 siz.dp = whd.dp;
2346 }
2347 }
2348 break;
2349 default:
2350 break;
2351 }
2352 p = node_next(p);
2353 }
2354 siz.ns = siz.wd;
2355 return siz;
2356}
2357
2358scaledwhd tex_natural_vsizes(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order, int inserts)
2359{
2360 scaledwhd siz = { .wd = 0, .ht = 0, .dp = 0, .ns = 0 };
2361 scaled gp = 0;
2362 scaled gm = 0;
2363 halfword f = p;
2364 int insertfound = 0;
2365 while (p && p != pp) {
2366 switch (node_type(p)) {
2367 case hlist_node:
2368 case vlist_node:
2369 {
2370 scaled shift = box_shift_amount(p);
2371 scaledwhd whd = tex_pack_dimensions(p);
2372 if (whd.wd + shift > siz.wd) {
2373 siz.wd = whd.wd + shift;
2374 }
2375 siz.ht += siz.dp + whd.ht;
2376 siz.dp = whd.dp;
2377 }
2378 break;
2379 case unset_node:
2380 siz.ht += siz.dp + box_height(p);
2381 siz.dp = box_depth(p);
2382 if (box_width(p) > siz.wd) {
2383 siz.wd = box_width(p);
2384 }
2385 break;
2386 case rule_node:
2387 siz.ht += siz.dp + rule_height(p);
2388 siz.dp = rule_depth(p);
2389 if (rule_width(p) > siz.wd) {
2390 siz.wd = rule_width(p);
2391 }
2392 break;
2393 case glue_node:
2394 {
2395 siz.ht += siz.dp + glue_amount(p);
2396 siz.dp = 0;
2397 if (is_leader(p)) {
2398 halfword gl = glue_leader_ptr(p);
2399 halfword wd = 0;
2400 switch (node_type(gl)) {
2401 case hlist_node:
2402 case vlist_node:
2403 wd = box_width(gl);
2404 break;
2405 case rule_node:
2406 wd = rule_width(gl);
2407 break;
2408 }
2409 if (wd > siz.wd) {
2410 siz.wd = wd;
2411 }
2412 }
2413 switch (g_sign) {
2414 case stretching_glue_sign:
2415 if (glue_stretch_order(p) == g_order) {
2416 gp += glue_stretch(p);
2417 }
2418 break;
2419 case shrinking_glue_sign:
2420 if (glue_shrink_order(p) == g_order) {
2421 gm += glue_shrink(p);
2422 }
2423 break;
2424 }
2425 break;
2426 }
2427 case kern_node:
2428 siz.ht += siz.dp + kern_amount(p);
2429 siz.dp = 0;
2430 break;
2431 case insert_node:
2432 if (inserts) {
2433 halfword height = tex_insert_height(p);
2434 if (height > 0) {
2435 siz.ht += siz.dp + height;
2436 siz.dp = 0;
2437 insertfound = 1;
2438 }
2439 }
2440 break;
2441 case glyph_node:
2442 tex_confusion("glyph in vpack");
2443 break;
2444 case disc_node:
2445 tex_confusion("discretionary in vpack");
2446 break;
2447 default:
2448 break;
2449 }
2450 p = node_next(p);
2451 }
2452 if (insertfound) {
2453 siz.ht += tex_insert_distances(f, pp ? node_next(pp) : null, NULL, NULL);
2454 }
2455 siz.ns = siz.ht;
2456 switch (g_sign) {
2457 case stretching_glue_sign:
2458 siz.ht += glueround((glueratio)(g_mult) * (glueratio)(gp));
2459 break;
2460 case shrinking_glue_sign:
2461 siz.ht -= glueround((glueratio)(g_mult) * (glueratio)(gm));
2462 break;
2463 }
2464 return siz;
2465}
2466
2467
2468
2469halfword tex_natural_width(halfword p, halfword pp, glueratio g_mult, int g_sign, int g_order)
2470{
2471 scaled wd = 0;
2472 scaled gp = 0;
2473 scaled gm = 0;
2474 while (p && p != pp) {
2475
2476 switch (node_type(p)) {
2477 case glyph_node:
2478 wd += tex_glyph_width(p);
2479 break;
2480 case hlist_node:
2481 case vlist_node:
2482 case unset_node:
2483 wd += box_width(p);
2484 break;
2485 case rule_node:
2486 wd += rule_width(p);
2487 break;
2488 case glue_node:
2489 wd += glue_amount(p);
2490 switch (g_sign) {
2491 case stretching_glue_sign:
2492 if (glue_stretch_order(p) == g_order) {
2493 gp += glue_stretch(p);
2494 }
2495 break;
2496 case shrinking_glue_sign:
2497 if (glue_shrink_order(p) == g_order) {
2498 gm += glue_shrink(p);
2499 }
2500 break;
2501 }
2502 break;
2503 case kern_node:
2504 wd += kern_amount(p);
2505 break;
2506 case disc_node:
2507 wd += tex_natural_width(disc_no_break(p), null, g_mult, g_sign, g_order);
2508 break;
2509 case math_node:
2510 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2511 wd += math_surround(p);
2512 } else {
2513 wd += math_amount(p);
2514 switch (g_sign) {
2515 case stretching_glue_sign:
2516 if (math_stretch_order(p) == g_order) {
2517 gp += math_stretch(p);
2518 }
2519 break;
2520 case shrinking_glue_sign:
2521 if (math_shrink_order(p) == g_order) {
2522 gm += math_shrink(p);
2523 }
2524 break;
2525 }
2526 }
2527 break;
2528 default:
2529 break;
2530 }
2531 p = node_next(p);
2532 }
2533 switch (g_sign) {
2534 case stretching_glue_sign:
2535 wd += glueround((glueratio) (g_mult) * (glueratio) (gp));
2536 break;
2537 case shrinking_glue_sign:
2538 wd -= glueround((glueratio) (g_mult) * (glueratio) (gm));
2539 break;
2540 }
2541 return wd;
2542}
2543
2544halfword tex_natural_hsize(halfword p, halfword *correction)
2545{
2546 scaled wd = 0;
2547 halfword c = null;
2548 while (p) {
2549 switch (node_type(p)) {
2550 case glyph_node:
2551 wd += tex_glyph_width(p);
2552 break;
2553 case hlist_node:
2554 case vlist_node:
2555 case unset_node:
2556 wd += box_width(p);
2557 break;
2558 case rule_node:
2559 wd += rule_width(p);
2560 break;
2561 case glue_node:
2562 wd += glue_amount(p);
2563 if (node_subtype(p) == correction_skip_glue) {
2564 c = p;
2565 }
2566 break;
2567 case kern_node:
2568 wd += kern_amount(p);
2569 break;
2570 case disc_node:
2571 wd += tex_natural_hsize(disc_no_break(p), NULL);
2572 break;
2573 case math_node:
2574 if (tex_math_glue_is_zero(p) || tex_ignore_math_skip(p)) {
2575 wd += math_surround(p);
2576 } else {
2577 wd += math_amount(p);
2578 }
2579 break;
2580 default:
2581 break;
2582 }
2583 p = node_next(p);
2584 }
2585 if (correction) {
2586 *correction = c;
2587 }
2588 return wd;
2589}
2590
2591halfword tex_natural_vsize(halfword p)
2592{
2593 scaled ht = 0;
2594 scaled dp = 0;
2595 while (p) {
2596 switch (node_type(p)) {
2597 case hlist_node:
2598 case vlist_node:
2599 ht += dp + box_height(p);
2600 dp = box_depth(p);
2601 break;
2602 case unset_node:
2603 ht += dp + box_height(p);
2604 dp = box_depth(p);
2605 break;
2606 case rule_node:
2607 ht += dp + rule_height(p);
2608 dp = rule_depth(p);
2609 break;
2610 case glue_node:
2611 ht += dp + glue_amount(p);
2612 dp = 0;
2613 break;
2614 case kern_node:
2615 ht += dp + kern_amount(p);
2616 dp = 0;
2617 break;
2618 default:
2619 break;
2620 }
2621 p = node_next(p);
2622 }
2623 return ht + dp;
2624}
2625
2626
2636
2637halfword tex_vpack(halfword p, scaled targetheight, int m, scaled targetdepth, singleword pack_direction, int retain, scaled *excess)
2638{
2639 scaled width = 0;
2640 scaled depth = 0;
2641 scaled height = 0;
2642 int has_uleader = 0;
2643
2644 halfword box = tex_new_node(vlist_node, unknown_list);
2645 int has_limit = box_limit_mode_vlist ? 1 : -1;
2646 (void) retain;
2647 box_dir(box) = pack_direction;
2648 box_shift_amount(box) = 0;
2649 box_list(box) = p;
2650 lmt_packaging_state.last_badness = 0;
2651 lmt_packaging_state.last_overshoot = 0;
2652 for (int i = normal_glue_order; i <= filll_glue_order; i++) {
2653 lmt_packaging_state.total_stretch[i] = 0;
2654 lmt_packaging_state.total_shrink[i] = 0;
2655 }
2656 while (p) {
2657
2663 halfword n = node_next(p);
2664 switch (node_type(p)) {
2665 case hlist_node:
2666 case vlist_node:
2667 {
2668
2674 scaled shift = box_shift_amount(p);
2675 scaledwhd whd = tex_pack_dimensions(p);
2676 if (whd.wd + shift > width) {
2677 width = whd.wd + shift;
2678 }
2679 height += depth + whd.ht;
2680 depth = whd.dp;
2681 tex_aux_promote_pre_migrated(box, p);
2682 tex_aux_promote_post_migrated(box, p);
2683 }
2684 break;
2685 case unset_node:
2686 height += depth + box_height(p);
2687 depth = box_depth(p);
2688 if (box_width(p) > width) {
2689 width = box_width(p);
2690 }
2691
2692 break;
2693 case rule_node:
2694 height += depth + rule_height(p);
2695 depth = rule_depth(p);
2696 if (rule_width(p) > width) {
2697 width = rule_width(p);
2698 }
2699 break;
2700 case glue_node:
2701
2702 height += depth + glue_amount(p);
2703 depth = 0;
2704 lmt_packaging_state.total_stretch[glue_stretch_order(p)] += glue_stretch(p);
2705 lmt_packaging_state.total_shrink[glue_shrink_order(p)] += glue_shrink(p);
2706 if (is_leader(p)) {
2707 halfword gl = glue_leader_ptr(p);
2708 scaled wd = 0;
2709 switch (node_type(gl)) {
2710 case hlist_node:
2711 case vlist_node:
2712 wd = box_width(gl);
2713 break;
2714 case rule_node:
2715 wd = rule_width(gl);
2716 break;
2717 }
2718 if (wd > width) {
2719 width = wd;
2720 }
2721 if (node_subtype(p) == u_leaders) {
2722 has_uleader = 1;
2723 }
2724 }
2725 if (! has_limit && tex_has_glue_option(p, glue_option_limit)) {
2726 has_limit = 1;
2727 }
2728 break;
2729 case kern_node:
2730 height += depth + kern_amount(p);
2731 depth = 0;
2732 break;
2733 case insert_node:
2734 if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_insert)) {
2735 halfword l = insert_list(p);
2736 tex_aux_post_migrate(box, p);
2737 while (l) {
2738 l = node_type(l) == insert_node ? tex_aux_post_migrate(box, l) : node_next(l);
2739 }
2740 }
2741 break;
2742 case mark_node:
2743 if (auto_migrating_mode_permitted(auto_migration_mode_par, auto_migrate_mark)) {
2744 tex_aux_post_migrate(box, p);
2745 }
2746 break;
2747 case glyph_node:
2748 tex_confusion("glyph in vpack");
2749 break;
2750 case disc_node:
2751 tex_confusion("discretionary in vpack");
2752 break;
2753 default:
2754 break;
2755 }
2756 p = n;
2757 }
2758 box_width(box) = width;
2759 if (depth > targetdepth) {
2760 height += depth - targetdepth;
2761 box_depth(box) = targetdepth;
2762 } else {
2763 box_depth(box) = depth;
2764 }
2765
2771 if (m == packing_additional) {
2772 targetheight += height;
2773 }
2774 box_height(box) = targetheight;
2775 {
2776 scaled targetexcess = targetheight - height;
2777
2778 if (excess) {
2779 *excess = targetexcess;
2780 }
2781 if (targetexcess == 0) {
2782 box_glue_sign(box) = normal_glue_sign;
2783 box_glue_order(box) = normal_glue_order;
2784 box_glue_set(box) = 0.0;
2785
2786 } else if (targetexcess > 0) {
2787
2788 halfword order = tex_aux_used_order(lmt_packaging_state.total_stretch);
2789 box_glue_order(box) = order;
2790 box_glue_sign(box) = stretching_glue_sign;
2791 if (lmt_packaging_state.total_stretch[order] != 0) {
2792 box_glue_set(box) = (glueratio) ((double) targetexcess / lmt_packaging_state.total_stretch[order]);
2793 } else {
2794
2795 box_glue_sign(box) = normal_glue_sign;
2796 box_glue_set(box) = 0.0;
2797 }
2798 if (order == normal_glue_order && box_list(box)) {
2799
2800 lmt_packaging_state.last_badness = tex_badness(targetexcess, lmt_packaging_state.total_stretch[normal_glue_order]);
2801 if (lmt_packaging_state.last_badness > vbadness_par) {
2802 int what = badness_mode_nothing;
2803 if (vbadness_mode_par & badness_mode_loose) {
2804 what = badness_mode_loose;
2805 } else if ((vbadness_mode_par & badness_mode_underfull) && (lmt_packaging_state.last_badness > 100)) {
2806 what = badness_mode_underfull;
2807 }
2808 if (what != badness_mode_nothing) {
2809 int callback_id = lmt_callback_defined(vpack_quality_callback);
2810 const char *verdict = what == badness_mode_underfull ? "underfull" : "loose";
2811 if (callback_id > 0) {
2812 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2813 verdict,
2814 lmt_packaging_state.last_badness,
2815 box,
2816 abs(lmt_packaging_state.pack_begin_line),
2817 lmt_input_state.input_line,
2818 tex_current_input_file_name()
2819 );
2820
2821 } else {
2822 tex_print_nlp();
2823 tex_print_format("%l[package: %s \\vbox (badness %i)", verdict, lmt_packaging_state.last_badness);
2824 goto COMMON_ENDING;
2825 }
2826 }
2827 }
2828 }
2829
2830 } else {
2831
2832 halfword order = tex_aux_used_order(lmt_packaging_state.total_shrink);
2833 box_glue_order(box) = order;
2834 box_glue_sign(box) = shrinking_glue_sign;
2835 if (lmt_packaging_state.total_shrink[order] != 0) {
2836 box_glue_set(box) = (glueratio) ((double) (-targetexcess) / lmt_packaging_state.total_shrink[order]);
2837 } else {
2838
2839 box_glue_sign(box) = normal_glue_sign;
2840 box_glue_set(box) = 0.0;
2841 }
2842 if (order == normal_glue_order && box_list(box)) {
2843 if (lmt_packaging_state.total_shrink[order] < -targetexcess) {
2844 int overshoot = -targetexcess - lmt_packaging_state.total_shrink[normal_glue_order];
2845 lmt_packaging_state.last_badness = scaling_factor_squared;
2846 lmt_packaging_state.last_overshoot = overshoot;
2847
2848 box_glue_set(box) = 1.0;
2849
2850 if (((overshoot > vfuzz_par) || (vbadness_par < 100)) && (vbadness_mode_par & badness_mode_overfull)) {
2851 int callback_id = lmt_callback_defined(vpack_quality_callback);
2852 if (callback_id > 0) {
2853 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2854 "overfull",
2855 overshoot,
2856 box,
2857 abs(lmt_packaging_state.pack_begin_line),
2858 lmt_input_state.input_line,
2859 tex_current_input_file_name()
2860 );
2861
2862 } else {
2863 tex_print_nlp();
2864 tex_print_format("%l[package: overfull \\vbox (%p too high)", overshoot);
2865 goto COMMON_ENDING;
2866 }
2867 }
2868 } else {
2869
2870 lmt_packaging_state.last_badness = tex_badness(-targetexcess, lmt_packaging_state.total_shrink[normal_glue_order]);
2871 if (lmt_packaging_state.last_badness > vbadness_par && (vbadness_mode_par & badness_mode_tight)) {
2872 int callback_id = lmt_callback_defined(vpack_quality_callback);
2873 if (callback_id > 0) {
2874 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "SdNddS->",
2875 "tight",
2876 lmt_packaging_state.last_badness,
2877 box,
2878 abs(lmt_packaging_state.pack_begin_line),
2879 lmt_input_state.input_line,
2880 tex_current_input_file_name()
2881 );
2882
2883 } else {
2884 tex_print_nlp();
2885 tex_print_format("%l[package: tight \\vbox (badness %i)", lmt_packaging_state.last_badness);
2886 goto COMMON_ENDING;
2887 }
2888 }
2889 }
2890 }
2891
2892 }
2893 }
2894 goto EXIT;
2895 COMMON_ENDING:
2896
2897 if (lmt_page_builder_state.output_active) {
2898 tex_print_format(" has occurred while \\output is active]");
2899 } else if (lmt_packaging_state.pack_begin_line != 0) {
2900 tex_print_format(" in alignment at lines %i--%i]", abs(lmt_packaging_state.pack_begin_line), lmt_input_state.input_line);
2901 } else {
2902 tex_print_format(" detected at line %i]", lmt_input_state.input_line);
2903 }
2904 tex_print_ln();
2905 tex_begin_diagnostic();
2906 tex_show_box(box);
2907 tex_end_diagnostic();
2908 EXIT:
2909 if (has_uleader) {
2910 set_box_package_state(box, package_u_leader_found);
2911 }
2912 if (has_limit > 0) {
2913 tex_limit(box);
2914 }
2915
2916 return box;
2917}
2918
2919halfword 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)
2920{
2921 halfword result = p;
2922 if (! just_pack) {
2923
2924 if (result && normalize_line_mode_option(flatten_h_leaders_mode)) {
2925 halfword c = result;
2926 while (c) {
2927 switch (node_type(c)) {
2928 case hlist_node:
2929 case vlist_node:
2930 if (has_box_package_state(c, package_u_leader_found) && ! is_box_package_state(state, package_u_leader_delayed)) {
2931 tex_flatten_leaders(c, grp, just_pack, uleader_before_vpack, 0);
2932 }
2933 break;
2934 }
2935 c = node_next(c);
2936 }
2937 }
2938 result = lmt_vpack_filter_callback(result, h, m, maxdepth, grp, direction, attr);
2939 }
2940 result = tex_vpack(result, h, m, maxdepth, (singleword) checked_direction_value(direction), retain, excess);
2941 if (result && normalize_par_mode_option(flatten_v_leaders_mode) && ! is_box_package_state(state, package_u_leader_delayed)) {
2942 tex_flatten_leaders(result, grp, just_pack, uleader_after_vpack, 0);
2943 }
2944 if (! just_pack) {
2945 result = lmt_packed_vbox_filter_callback(result, grp);
2946 }
2947 return result;
2948}
2949
2950static scaled tex_aux_first_height(halfword boxnode)
2951{
2952 halfword list = box_list(boxnode);
2953 if (list) {
2954 switch (node_type(list)) {
2955 case hlist_node:
2956 case vlist_node:
2957 return box_height(list);
2958 case rule_node:
2959 return rule_height(list);
2960 }
2961 }
2962 return 0;
2963}
2964
2965static void tex_aux_set_vnature(halfword boxnode, int nature)
2966{
2967 switch (nature) {
2968 case vtop_code:
2969 case tsplit_code:
2970 case vbalanced_top_code:
2971 {
2972
2979 scaled height = tex_aux_first_height(boxnode);
2980 box_depth(boxnode) = box_total(boxnode) - height;
2981 box_height(boxnode) = height;
2982 box_package_state(boxnode) = vtop_package_state;
2983 }
2984 break;
2985 case vbox_code:
2986 case vsplit_code:
2987 case vbalance_code:
2988 case vbalanced_box_code:
2989
2990
2991
2992
2993 case flush_mvl_box_code:
2994 box_package_state(boxnode) = vbox_package_state;
2995 break;
2996 case dbox_code:
2997 case dsplit_code:
2998 box_package_state(boxnode) = dbox_package_state;
2999 break;
3000 }
3001}
3002
3003
3004
3008
3009void tex_run_vcenter(void)
3010{
3011 tex_aux_scan_full_spec(direct_box_flag, vcenter_group, direction_l2r, 0, 0, -1, 0, 0);
3012 tex_normal_paragraph(vcenter_par_context);
3013 tex_push_nest();
3014 cur_list.mode = internal_vmode;
3015 cur_list.prev_depth = ignore_depth_criterion_par;
3016 if (every_vbox_par) {
3017 tex_begin_token_list(every_vbox_par, every_vbox_text);
3018 }
3019}
3020
3021void tex_finish_vcenter_group(void)
3022{
3023 if (! tex_wrapped_up_paragraph(vcenter_par_context, 1)) {
3024 halfword p;
3025 tex_end_paragraph(vcenter_group, vcenter_par_context);
3026 tex_package(vbox_code);
3027 p = tex_pop_tail();
3028 if (p) {
3029 switch (node_type(p)) {
3030 case vlist_node:
3031 {
3032 scaled delta = box_total(p);
3033 box_height(p) = tex_half_scaled(delta);
3034 box_depth(p) = delta - box_height(p);
3035 break;
3036 }
3037 case simple_noad:
3038 node_subtype(p) = vcenter_noad_subtype;
3039 break;
3040
3044 }
3045 tex_tail_append(p);
3046 }
3047 }
3048}
3049
3050void tex_package(singleword nature)
3051{
3052 int grp = cur_group;
3053 scaled maxdepth = box_max_depth_par;
3054 tex_unsave();
3055 lmt_save_state.save_stack_data.ptr -= saved_box_n_of_records;
3056 {
3057 halfword boxnode = null;
3058
3062 halfword slot = saved_box_slot;
3063 halfword context = saved_box_context;
3064 halfword dirptr = saved_box_dir_pointer;
3065 halfword orientation = saved_box_orientation;
3066 halfword anchor = saved_box_anchor;
3067 halfword geometry = saved_box_geometry;
3068 halfword attrlist = saved_box_attr_list;
3069 halfword state = saved_box_state;
3070 scaled shift = saved_box_shift;
3071 halfword source = saved_box_source;
3072 halfword target = saved_box_target;
3073 halfword axis = saved_box_axis;
3074 halfword mainclass = saved_box_class;
3075 halfword callback = saved_box_callback;
3076 halfword leaders = saved_box_leaders;
3077 halfword options = saved_box_options;
3078 scaled xoffset = saved_box_xoffset;
3079 scaled yoffset = saved_box_yoffset;
3080 scaled xmove = saved_box_xmove;
3081 scaled ymove = saved_box_ymove;
3082 if (cur_list.mode == restricted_hmode) {
3083 boxnode = tex_filtered_hpack(
3084 cur_list.head, cur_list.tail,
3085 saved_box_amount, saved_box_packing, grp,
3086 saved_box_direction, saved_box_pack, attrlist, state, saved_box_retain
3087 );
3088 node_subtype(boxnode) = hbox_list;
3089 if (options & saved_box_reverse_option) {
3090 box_list(boxnode) = tex_reversed_node_list(box_list(boxnode));
3091 }
3092 box_package_state(boxnode) = hbox_package_state;
3093 } else {
3094 boxnode = tex_filtered_vpack(
3095 node_next(cur_list.head),
3096 saved_box_amount, saved_box_packing, maxdepth, grp,
3097 saved_box_direction, saved_box_pack, attrlist, state, saved_box_retain,
3098 NULL
3099 );
3100 box_package_state(boxnode) = hbox_package_state;
3101 tex_aux_set_vnature(boxnode, nature);
3102 }
3103 if (options & saved_box_limit_option && box_list(boxnode)) {
3104 tex_limit(boxnode);
3105 }
3106 if (dirptr) {
3107
3108 tex_flush_node_list(lmt_dir_state.text_dir_ptr);
3109 lmt_dir_state.text_dir_ptr = dirptr;
3110 }
3111
3116 tex_attach_attribute_list_attribute(boxnode, attrlist);
3117 delete_attribute_reference(attrlist);
3118
3119 if (tex_has_geometry(geometry, offset_geometry) || tex_has_geometry(geometry, orientation_geometry)) {
3120 scaled wd = box_width(boxnode);
3121 scaled ht = box_height(boxnode);
3122 scaled dp = box_depth(boxnode);
3123 if (xmove) {
3124 xoffset = tex_aux_checked_dimension1(xoffset + xmove);
3125 wd = tex_aux_checked_dimension2(wd + xmove);
3126 }
3127 if (ymove) {
3128 yoffset = tex_aux_checked_dimension1(yoffset + ymove);
3129 ht = tex_aux_checked_dimension2(ht + ymove);
3130 dp = tex_aux_checked_dimension2(dp - ymove);
3131 }
3132 box_w_offset(boxnode) = wd;
3133 box_h_offset(boxnode) = ht;
3134 box_d_offset(boxnode) = dp;
3135 switch (orientationonly(orientation)) {
3136 case 0 :
3137 break;
3138 case 2 :
3139 box_height(boxnode) = dp;
3140 box_depth(boxnode) = ht;
3141 geometry |= orientation_geometry;
3142 break;
3143 case 1 :
3144 case 3 :
3145 box_width(boxnode) = ht + dp;
3146 box_height(boxnode) = wd;
3147 box_depth(boxnode) = 0;
3148 geometry |= orientation_geometry;
3149 break;
3150 case 4 :
3151 box_height(boxnode) = ht + dp;
3152 box_depth(boxnode) = 0;
3153 geometry |= orientation_geometry;
3154 break;
3155 case 5 :
3156 box_height(boxnode) = 0;
3157 box_depth(boxnode) = ht + dp;
3158 geometry |= orientation_geometry;
3159 break;
3160 default :
3161 break;
3162 }
3163 if (xoffset || yoffset) {
3164 box_x_offset(boxnode) = xoffset;
3165 box_y_offset(boxnode) = yoffset;
3166 geometry |= offset_geometry;
3167 }
3168 }
3169 if (source || target) {
3170 box_source_anchor(boxnode) = source;
3171 box_target_anchor(boxnode) = target;
3172 geometry |= anchor_geometry;
3173 }
3174 box_anchor(boxnode) = anchor;
3175 box_orientation(boxnode) = orientation;
3176 box_geometry(boxnode) = (singleword) geometry;
3177 if (options & saved_box_container_option) {
3178 node_subtype(boxnode) = container_list;
3179 } else if (options & saved_box_mathtext_option) {
3180 node_subtype(boxnode) = math_text_list;
3181 }
3182 if (axis) {
3183 tex_add_box_option(boxnode, box_option_no_math_axis);
3184 } else {
3185 tex_remove_box_option(boxnode, box_option_no_math_axis);
3186 }
3187if (options & saved_box_discardable_option) {
3188 box_options(boxnode) |= box_option_discardable;
3189}
3190 box_package_state(boxnode) |= (singleword) state;
3191 tex_pop_nest();
3192 tex_box_end(context, boxnode, shift, mainclass, slot, callback, leaders);
3193 }
3194}
3195
3196static int local_box_mapping[] = {
3197 [local_left_box_box_code ] = local_left_box_code,
3198 [local_right_box_box_code ] = local_right_box_code,
3199 [local_middle_box_box_code] = local_middle_box_code
3200};
3201
3202void tex_run_unpackage(void)
3203{
3204 int code = cur_chr;
3205 switch (code) {
3206 case box_code:
3207 case copy_code:
3208 case unpack_code:
3209 {
3210 halfword index = tex_scan_box_register_number();
3211 halfword box = box_register(index);
3212 if (box) {
3213 int bad = 0;
3214 switch (cur_list.mode) {
3215 case vmode:
3216 case internal_vmode:
3217 if (node_type(box) != vlist_node) {
3218 bad = 1;
3219 }
3220 break;
3221 case hmode:
3222 case restricted_hmode:
3223 if (node_type(box) != hlist_node) {
3224 bad = 1;
3225 }
3226 break;
3227 case mmode:
3228 case inline_mmode:
3229 bad = 1;
3230 break;
3231 }
3232 if (bad) {
3233 tex_handle_error(
3234 normal_error_type,
3235 "Incompatible list can't be unboxed",
3236 "Sorry, Pandora. (You sneaky devil.) I refuse to unbox an \\hbox in vertical mode\n"
3237 "or vice versa. And I can't open any boxes in math mode."
3238 );
3239 } else {
3240
3244 halfword tail = cur_list.tail;
3245 halfword list = box_list(box);
3246 halfword pre_migrated = code == unpack_code ? null : box_pre_migrated(box);
3247 halfword post_migrated = code == unpack_code ? null : box_post_migrated(box);
3248
3249 halfword pre_adjusted = code == unpack_code ? null : box_pre_adjusted(box);
3250 halfword post_adjusted = code == unpack_code ? null : box_post_adjusted(box);
3251 int prunekerns = list && node_type(box) == hlist_node && normalize_line_mode_option(remove_margin_kerns_mode);
3252
3261
3289 if (pre_adjusted) {
3290 if (code == copy_code) {
3291 pre_adjusted = tex_copy_node_list(pre_adjusted, null);
3292 } else {
3293 box_pre_adjusted(box) = null;
3294 }
3295 tail = tex_flush_adjust_prepend(pre_adjusted, tail);
3296 }
3297 if (pre_migrated) {
3298 if (code == copy_code) {
3299 pre_migrated = tex_copy_node_list(pre_migrated, null);
3300 } else {
3301 box_pre_migrated(box) = null;
3302 }
3303 tex_try_couple_nodes(tail, pre_migrated);
3304 tail = tex_tail_of_node_list(pre_migrated);
3305 }
3306 if (list) {
3307 if (code == copy_code) {
3308 list = tex_copy_node_list(list, null);
3309 } else {
3310 box_list(box) = null;
3311 }
3312 tex_try_couple_nodes(tail, list);
3313 tail = tex_tail_of_node_list(list);
3314 }
3315 if (post_migrated) {
3316 if (code == copy_code) {
3317 post_migrated = tex_copy_node_list(post_migrated, null);
3318 } else {
3319 box_post_migrated(box) = null;
3320 }
3321 tex_try_couple_nodes(tail, post_migrated);
3322 tail = tex_tail_of_node_list(post_migrated);
3323 }
3324 if (post_adjusted) {
3325 if (code == copy_code) {
3326 post_adjusted = tex_copy_node_list(post_adjusted, null);
3327 } else {
3328 box_post_adjusted(box) = null;
3329 }
3330 tail = tex_flush_adjust_append(post_adjusted, tail);
3331 }
3332 if (code != copy_code) {
3333 box_register(index) = null;
3334 tex_flush_node(box);
3335 }
3336 cur_list.tail = prunekerns ? tex_wipe_margin_kerns(cur_list.head) : tex_tail_of_node_list(tail);
3337 }
3338 }
3339 break;
3340 }
3341 case page_discards_code:
3342 {
3343 tex_try_couple_nodes(cur_list.tail, lmt_packaging_state.page_discards_head);
3344 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3345 lmt_packaging_state.page_discards_head = null;
3346 break;
3347 }
3348 case split_discards_code:
3349 case copy_split_discards_code:
3350 {
3351 halfword discards = lmt_packaging_state.split_discards_head;
3352 if (discards) {
3353 if (code == copy_split_discards_code) {
3354 discards = tex_copy_node_list(discards, null);
3355 }
3356 tex_couple_nodes(cur_list.tail, discards);
3357 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3358 lmt_packaging_state.split_discards_head = null;
3359 }
3360 break;
3361 }
3362 case insert_box_code:
3363 case insert_copy_code:
3364 {
3365
3370 halfword index = tex_scan_integer(0, NULL, NULL);
3371 if (tex_valid_insert_id(index)) {
3372 halfword boxnode = tex_get_insert_content(index);
3373 if (boxnode) {
3374 if (! is_v_mode(cur_list.mode)) {
3375 tex_handle_error(
3376 normal_error_type,
3377 "Unpacking an inserts can only happen in vertical mode.",
3378 NULL
3379 );
3380 } else if (node_type(boxnode) == vlist_node) {
3381 if (code == insert_copy_code) {
3382 boxnode = tex_copy_node(boxnode);
3383 } else {
3384 tex_set_insert_content(index, null);
3385 }
3386 if (boxnode) {
3387 halfword list = box_list(boxnode);
3388 if (list) {
3389 tex_try_couple_nodes(cur_list.tail, list);
3390 cur_list.tail = tex_tail_of_node_list(list);
3391 box_list(boxnode) = null;
3392 }
3393 tex_flush_node(boxnode);
3394 }
3395 } else {
3396
3397 }
3398 }
3399 }
3400 break;
3401 }
3402 case local_left_box_box_code:
3403 case local_right_box_box_code:
3404 case local_middle_box_box_code:
3405 {
3406 tex_try_couple_nodes(cur_list.tail, tex_get_local_boxes(local_box_mapping[code]));
3407 cur_list.tail = tex_tail_of_node_list(cur_list.tail);
3408 break;
3409 }
3410 default:
3411 {
3412 tex_confusion("weird unpackage");
3413 break;
3414 }
3415 }
3416}
3417
3418
3428
3429static halfword tex_aux_depth_correction(halfword b, const line_break_properties *properties)
3430{
3431
3432 halfword p;
3433 halfword height = has_box_package_state(b, dbox_package_state) ? tex_aux_first_height(b) : box_height(b);
3434 halfword depth = cur_list.prev_depth;
3435 if (properties) {
3436 scaled d = glue_amount(properties->baseline_skip) - depth - height;
3437 if (d < properties->line_skip_limit) {
3438 p = tex_new_glue_node(properties->line_skip, line_skip_glue);
3439 } else {
3440 p = tex_new_glue_node(properties->baseline_skip, baseline_skip_glue);
3441 glue_amount(p) = d;
3442 }
3443 } else {
3444 scaled d = glue_amount(baseline_skip_par) - depth - height;
3445 if (d < line_skip_limit_par) {
3446 p = tex_new_param_glue_node(line_skip_code, line_skip_glue);
3447 } else {
3448 p = tex_new_param_glue_node(baseline_skip_code, baseline_skip_glue);
3449 glue_amount(p) = d;
3450 }
3451 }
3452 return p;
3453}
3454
3455void tex_append_to_vlist(halfword b, int location, const line_break_properties *properties)
3456{
3457 if (location >= 0) {
3458 halfword result = null;
3459 halfword next_depth = ignore_depth_criterion_par;
3460 int prev_set = 0;
3461 int check_depth = 0;
3462 if (lmt_append_to_vlist_callback(b, location, cur_list.prev_depth, &result, &next_depth, &prev_set, &check_depth)) {
3463 if (prev_set) {
3464 cur_list.prev_depth = next_depth;
3465 }
3466 if (check_depth && result && (cur_list.prev_depth > ignore_depth_criterion_par)) {
3467
3471 switch (node_type(result)) {
3472 case hlist_node:
3473 case vlist_node:
3474 case rule_node:
3475 {
3476 halfword glue = tex_aux_depth_correction(result, properties);
3477 tex_tail_append(glue);
3478 break;
3479 }
3480 }
3481 }
3482 if (result) {
3483 tex_tail_append_list(result);
3484 }
3485 return;
3486 }
3487 }
3488 if (cur_list.prev_depth > ignore_depth_criterion_par) {
3489 halfword glue = tex_aux_depth_correction(b, properties);
3490 tex_tail_append(glue);
3491 }
3492 tex_tail_append(b);
3493 cur_list.prev_depth = box_depth(b);
3494}
3495
3496
3519
3520halfword tex_prune_page_top(halfword p, int s)
3521{
3522
3523 halfword prev_p = temp_head;
3524 halfword r = null;
3525 node_next(temp_head) = p;
3526 while (p) {
3527 switch (node_type(p)) {
3528 case hlist_node:
3529 case vlist_node:
3530 case rule_node:
3531 {
3532
3533 halfword h = node_type(p) == rule_node ? rule_height(p) : box_height(p);
3534 halfword q = tex_new_param_glue_node(split_top_skip_code, split_top_skip_glue);
3535
3536 tex_couple_nodes(prev_p, q);
3537 tex_couple_nodes(q, p);
3538 glue_amount(q) = glue_amount(q) > h ? glue_amount(q) - h : 0;
3539 p = null;
3540 }
3541 break;
3542 case boundary_node:
3543
3544 case whatsit_node:
3545 case mark_node:
3546 case insert_node:
3547 prev_p = p;
3548 p = node_next(prev_p);
3549 break;
3550 case glue_node:
3551 case kern_node:
3552 case penalty_node:
3553 {
3554 halfword q = p;
3555 p = node_next(q);
3556 node_next(q) = null;
3557 node_next(prev_p) = p;
3558 if (s) {
3559 if (lmt_packaging_state.split_discards_head) {
3560 node_next(r) = q;
3561 } else {
3562 lmt_packaging_state.split_discards_head = q;
3563 }
3564 r = q;
3565 } else {
3566 tex_flush_node_list(q);
3567 }
3568 }
3569 break;
3570 default:
3571 tex_confusion("pruning page top");
3572 break;
3573 }
3574 }
3575 return node_next(temp_head);
3576}
3577
3578
3601
3602static halfword tex_aux_vert_badness(scaled goal, scaled active_height[])
3603{
3604 if (active_height[total_advance_amount] < goal) {
3605 if (active_height[total_fi_amount] || active_height[total_fil_amount] || active_height[total_fill_amount] || active_height[total_filll_amount]) {
3606 return 0;
3607 } else {
3608 return tex_badness(goal - active_height[total_advance_amount], active_height[total_stretch_amount]);
3609 }
3610 } else if (active_height[total_advance_amount] - goal > active_height[total_shrink_amount]) {
3611 return awful_bad;
3612 } else {
3613 return tex_badness(active_height[total_advance_amount] - goal, active_height[total_shrink_amount]);
3614 }
3615}
3616
3617static halfword tex_aux_vert_costs(halfword badness, halfword penalty)
3618{
3619 if (badness >= awful_bad) {
3620 return badness;
3621 } else if (penalty <= eject_penalty) {
3622 return penalty;
3623 } else if (badness < infinite_bad) {
3624 return badness + penalty;
3625 } else {
3626 return deplorable;
3627 }
3628}
3629
3630static void tex_aux_vsplit_callback_initialize(int callback_id, halfword checks, halfword current, scaled height, scaled depth, scaled extra)
3631{
3632 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddNddd->",
3633 initialize_show_vsplit_context,
3634 checks,
3635 current,
3636 height,
3637 depth,
3638 extra
3639 );
3640}
3641
3642static void tex_aux_vsplit_callback_continue(int callback_id, halfword checks, halfword current, scaled height, scaled depth, scaled total, halfword penalty)
3643{
3644 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddNdddd->",
3645 continue_show_vsplit_context,
3646 checks,
3647 current,
3648 height,
3649 depth,
3650 total,
3651 penalty
3652 );
3653}
3654
3655static void tex_aux_vsplit_callback_check(int callback_id, halfword checks, halfword current, scaled height, scaled depth, scaled total, halfword penalty, halfword badness, halfword costs)
3656{
3657 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddNdddddd->",
3658 check_show_vsplit_context,
3659 checks,
3660 current,
3661 height,
3662 depth,
3663 total,
3664 penalty,
3665 badness,
3666 costs
3667 );
3668}
3669
3670static void tex_aux_vsplit_callback_quit(int callback_id, halfword checks, halfword current, scaled height, scaled depth, scaled total, halfword penalty, halfword badness, halfword costs)
3671{
3672 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddNdddddd->",
3673 quit_show_vsplit_context,
3674 checks,
3675 current,
3676 height,
3677 depth,
3678 total,
3679 penalty,
3680 badness,
3681 costs
3682 );
3683}
3684
3685static void tex_aux_vsplit_callback_wrapup(int callback_id, halfword checks, halfword best)
3686{
3687 lmt_run_callback(lmt_lua_state.lua_instance, callback_id, "ddddddd->",
3688 wrapup_show_vsplit_context,
3689 checks,
3690 best,
3691 lmt_packaging_state.split_last_height,
3692 lmt_packaging_state.split_last_depth,
3693 lmt_packaging_state.split_last_stretch,
3694 lmt_packaging_state.split_last_shrink
3695 );
3696}
3697
3698halfword tex_vert_break(halfword current, scaled height, scaled depth, int callback, scaled extra)
3699{
3700
3704 halfword previous = current;
3705
3706 halfword penalty = 0;
3707 int penalty_state = 0;
3708
3709 halfword least_cost = awful_bad;
3710
3711 halfword best_place = null;
3712
3713 scaled previous_depth = 0;
3714
3715 scaled active_height[10] = { 0 };
3716 scaled passive_height[10] = { 0 };
3717
3718 int checks = callback ? vsplit_checks_par : 0;
3719 int callbackid = checks ? lmt_callback_defined(show_vsplit_callback) : 0;
3720 if (callbackid) {
3721 tex_aux_vsplit_callback_initialize(callbackid, checks, current, height, depth, extra);
3722 }
3723 while (1) {
3724
3731 if (current) {
3732
3737 switch (node_type(current)) {
3738 case hlist_node:
3739 case vlist_node:
3740
3744
3753
3754
3755
3756
3757
3758
3759
3760
3761 active_height[total_advance_amount] += previous_depth + box_height(current);
3762 previous_depth = box_depth(current);
3763 goto NOT_FOUND;
3764 case rule_node:
3765 active_height[total_advance_amount] += previous_depth + rule_height(current);
3766 previous_depth = rule_depth(current);
3767 goto NOT_FOUND;
3768 case boundary_node:
3769 case whatsit_node:
3770 goto NOT_FOUND;
3771 case glue_node:
3772 if (precedes_break(previous)) {
3773
3774 penalty = 0;
3775 break;
3776 } else {
3777 goto UPDATE_HEIGHTS;
3778 }
3779 case kern_node:
3780 if (node_next(current) && node_type(node_next(current)) == glue_node) {
3781 penalty = 0;
3782 break;
3783 } else {
3784 goto UPDATE_HEIGHTS;
3785 }
3786 case penalty_node:
3787 penalty = penalty_amount(current);
3788 if (tex_has_penalty_option(current, penalty_option_widowed)) {
3789 penalty_state = penalty_option_widowed;
3790 } else if (tex_has_penalty_option(current, penalty_option_clubbed)) {
3791 penalty_state = penalty_option_clubbed;
3792 } else {
3793 penalty_state = penalty_option_normal;
3794 }
3795 break;
3796 case mark_node:
3797 case insert_node:
3798 goto NOT_FOUND;
3799 default:
3800 tex_confusion("vertical break");
3801 break;
3802 }
3803 } else {
3804 penalty = eject_penalty;
3805 }
3806
3810 if (penalty < infinite_penalty) {
3811
3812 int badness = tex_aux_vert_badness(height, active_height);
3813 int costs = tex_aux_vert_costs(badness, penalty);
3814 if (badness == awful_bad && penalty_state) {
3815 int b = tex_aux_vert_badness(height + extra, active_height);
3816 int c = tex_aux_vert_costs(b, penalty);
3817
3818 badness = b;
3819 costs = c;
3820 height += extra;
3821 penalty_state = penalty_option_normal;
3822 extra = 0;
3823 }
3824 if (costs <= least_cost) {
3825 best_place = current;
3826 least_cost = costs;
3827 for (int i = total_advance_amount; i <= total_stretch_amount; i++) {
3828 passive_height[i] = active_height[i];
3829 }
3830 lmt_packaging_state.best_height_plus_depth = passive_height[total_advance_amount];
3831
3835 if (lmt_packaging_state.best_height_plus_depth > (height + previous_depth) && costs < awful_bad) {
3836 lmt_packaging_state.best_height_plus_depth = height + previous_depth;
3837 }
3838 } else {
3839
3840 }
3841 if ((costs == awful_bad) || (penalty <= eject_penalty)) {
3842 if (callbackid) {
3843 tex_aux_vsplit_callback_quit(callbackid, checks, current, active_height[total_advance_amount], previous_depth, passive_height[total_advance_amount], penalty, badness, costs);
3844 }
3845 goto WRAPUP;
3846 } else {
3847 if (callbackid) {
3848 tex_aux_vsplit_callback_check(callbackid, checks, current, active_height[total_advance_amount], previous_depth, passive_height[total_advance_amount], penalty, badness, costs);
3849 }
3850 }
3851 } else {
3852 if (callbackid) {
3853 tex_aux_vsplit_callback_continue(callbackid, checks, current, active_height[total_advance_amount], previous_depth, passive_height[total_advance_amount], penalty);
3854 }
3855 }
3856 UPDATE_HEIGHTS:
3857
3863 switch(node_type(current)) {
3864 case kern_node:
3865 active_height[total_advance_amount] += previous_depth + kern_amount(current);
3866 previous_depth = 0;
3867 goto KEEP_GOING;
3868 case glue_node:
3869 active_height[total_stretch_amount + glue_stretch_order(current)] += glue_stretch(current);
3870 active_height[total_shrink_amount] += glue_shrink(current);
3871 if (glue_shrink_order(current) != normal_glue_order && glue_shrink(current)) {
3872
3877 tex_handle_error(
3878 normal_error_type,
3879 "Infinite glue shrinkage found in box being split",
3880 "The box you are \\vsplitting contains some infinitely shrinkable glue, e.g.,\n"
3881 "'\\vss' or '\\vskip 0pt minus 1fil'. Such glue doesn't belong there; but you can\n"
3882 "safely proceed, since the offensive shrinkability has been made finite."
3883 );
3884 glue_shrink_order(current) = normal_glue_order;
3885 }
3886 active_height[total_advance_amount] += previous_depth + glue_amount(current);
3887 previous_depth = 0;
3888 goto KEEP_GOING;
3889 }
3890 NOT_FOUND:
3891 if (previous_depth > depth) {
3892 active_height[total_advance_amount] += previous_depth - depth;
3893 previous_depth = depth;
3894 }
3895 KEEP_GOING:
3896 previous = current;
3897 current = node_next(current);
3898 }
3899 WRAPUP:
3900 lmt_packaging_state.split_last_height = passive_height[total_advance_amount];
3901 lmt_packaging_state.split_last_depth = previous_depth;
3902 lmt_packaging_state.split_last_stretch = passive_height[total_stretch_amount];
3903 lmt_packaging_state.split_last_shrink = passive_height[total_shrink_amount];
3904 if (callbackid) {
3905 tex_aux_vsplit_callback_wrapup(callbackid, checks, best_place);
3906 }
3907 return best_place;
3908}
3909
3910
3928
3929halfword tex_vsplit(halfword n, scaled h, int m)
3930{
3931
3932 halfword v = box_register(n);
3933 tex_flush_node_list(lmt_packaging_state.split_discards_head);
3934 lmt_packaging_state.split_discards_head = null;
3935 for (halfword i = 0; i <= lmt_mark_state.mark_data.ptr; i++) {
3936 tex_delete_mark(i, split_first_mark_code);
3937 tex_delete_mark(i, split_bot_mark_code);
3938 }
3939
3940 if (! v) {
3941 return null;
3942 } else if (node_type(v) != vlist_node) {
3943 tex_handle_error(
3944 normal_error_type,
3945 "\\vsplit needs a \\vbox",
3946 "The box you are trying to split is an \\hbox. I can't split such a box, so I''ll\n"
3947 "leave it alone."
3948 );
3949 return null;
3950 } else {
3951
3952 halfword q = tex_vert_break(box_list(v), h, split_max_depth_par, 1, split_extra_height_par);
3953
3960 halfword p = box_list(v);
3961
3962 int vdir = box_dir(v);
3963 if (p == q) {
3964 box_list(v) = null;
3965 } else {
3966 while (1) {
3967 if (node_type(p) == mark_node) {
3968 tex_update_split_mark(p);
3969 }
3970 if (node_next(p) == q) {
3971 node_next(p) = null;
3972 break;
3973 } else {
3974 p = node_next(p);
3975 }
3976 }
3977 }
3978 q = tex_prune_page_top(q, saving_vdiscards_par > 0);
3979 p = box_list(v);
3980 box_list(v) = null;
3981 tex_flush_node(v);
3982 if (q) {
3983 box_register(n) = tex_filtered_vpack(q, 0, packing_additional, max_depth_par, split_keep_group, vdir, 0, 0, 0, holding_none_option, NULL);
3984 } else {
3985
3986 box_register(n) = null;
3987 }
3988 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);
3989 }
3990}
3991
3992
3999
4000void tex_begin_box(int boxcontext, scaled shift, halfword slot, halfword callback, halfword leaders)
4001{
4002 halfword code = cur_chr;
4003 halfword boxnode = null;
4004 switch (code) {
4005 case box_code:
4006 {
4007 halfword n = tex_scan_box_register_number();
4008 boxnode = box_register(n);
4009
4010 box_register(n) = null;
4011 break;
4012 }
4013 case copy_code:
4014 {
4015 halfword n = tex_scan_box_register_number();
4016 boxnode = box_register(n) ? tex_copy_node(box_register(n)) : null;
4017 break;
4018 }
4019
4020
4021 case last_box_code:
4022
4026 boxnode = null;
4027 if (is_m_mode(cur_list.mode)) {
4028 tex_you_cant_error(
4029 "Sorry; this \\lastbox will be void."
4030 );
4031 } else if (cur_list.mode == vmode && cur_list.head == cur_list.tail) {
4032 tex_you_cant_error(
4033 "Sorry...I usually can't take things from the current page.\n"
4034 "This \\lastbox will therefore be void."
4035 );
4036 } else if (cur_list.head != cur_list.tail) {
4037 switch (node_type(cur_list.tail)) {
4038 case hlist_node:
4039 case vlist_node:
4040 {
4041
4042 halfword q = node_prev(cur_list.tail);
4043 if (! q || node_next(q) != cur_list.tail) {
4044 q = cur_list.head;
4045 while (node_next(q) != cur_list.tail)
4046 q = node_next(q);
4047 }
4048 tex_uncouple_node(cur_list.tail);
4049 boxnode = cur_list.tail;
4050 box_shift_amount(boxnode) = 0;
4051 cur_list.tail = q;
4052 node_next(cur_list.tail) = null;
4053 }
4054 break;
4055 }
4056 }
4057 break;
4058 case tsplit_code:
4059 case vsplit_code:
4060 case dsplit_code:
4061 {
4062
4067 halfword mode = packing_exactly ;
4068 halfword index = tex_scan_box_register_number();
4069 halfword size = 0;
4070 halfword attrlist = null;
4071 while (1) {
4072 switch (tex_scan_character("atuATU", 0, 1, 0)) {
4073 case 0:
4074 goto DONE1;
4075 case 'a': case 'A':
4076 if (tex_scan_mandate_keyword("attr", 1)) {
4077 attrlist = tex_scan_attribute(attrlist);
4078 }
4079 break;
4080 case 't': case 'T':
4081 if (tex_scan_mandate_keyword("to", 1)) {
4082 mode = packing_exactly;
4083 size = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
4084 }
4085 break;
4086 case 'u': case 'U':
4087 if (tex_scan_mandate_keyword("upto", 1)) {
4088 mode = packing_additional;
4089 size = tex_scan_dimension(0, 0, 0, 0, NULL, NULL);
4090 }
4091 break;
4092 default:
4093 tex_aux_show_keyword_error("attr|upto|to");
4094 goto DONE1;
4095 }
4096 }
4097 DONE1:
4098 boxnode = tex_vsplit(index, size, mode);
4099 tex_aux_set_vnature(boxnode, code);
4100 if (attrlist) {
4101 tex_attach_attribute_list_attribute(boxnode, attrlist);
4102 }
4103 }
4104 break;
4105 case vbalance_code:
4106 {
4107
4108 halfword index = tex_scan_box_register_number();
4109 halfword mode = packing_exactly;
4110 halfword trial = 0;
4111 while (1) {
4112 switch (tex_scan_character("aetAET", 0, 1, 0)) {
4113 case 0:
4114 goto BALANCE;
4115 case 'e': case 'E':
4116 if (tex_scan_mandate_keyword("exactly", 1)) {
4117 mode = packing_exactly;
4118 }
4119 break;
4120 case 'a': case 'A':
4121 if (tex_scan_mandate_keyword("additional", 1)) {
4122 mode = packing_additional;
4123 }
4124 break;
4125 case 't': case 'T':
4126 if (tex_scan_mandate_keyword("trial", 1)) {
4127
4128 trial = 1;
4129 }
4130 break;
4131 default:
4132 tex_aux_show_keyword_error("exactly|additional|trial");
4133 goto BALANCE;
4134 }
4135 }
4136 BALANCE:
4137 boxnode = tex_vbalance(index, mode, trial);
4138 }
4139 break;
4140 case vbalanced_box_code:
4141 case vbalanced_top_code:
4142 {
4143 halfword index = tex_scan_box_register_number();
4144 boxnode = tex_vbalanced(index);
4145 }
4146 break;
4147 case vbalanced_insert_code:
4148 {
4149 halfword index = tex_scan_box_register_number();
4150 halfword insert = -1;
4151 halfword options = 0;
4152 while (1) {
4153 switch (tex_scan_character("diDI", 0, 1, 0)) {
4154 case 0:
4155 goto GETINSERT;
4156 case 'd': case 'D':
4157 if (tex_scan_mandate_keyword("descend", 1)) {
4158 options |= balance_insert_descend;
4159 }
4160 break;
4161 case 'i': case 'I':
4162 if (tex_scan_mandate_keyword("index", 1)) {
4163 insert = tex_scan_insert_index();
4164 }
4165 break;
4166 default:
4167 tex_aux_show_keyword_error("descend|index");
4168 goto GETINSERT;
4169 }
4170 }
4171 GETINSERT:
4172 if (insert < 0) {
4173 insert = tex_scan_insert_index();
4174 }
4175 boxnode = tex_vbalanced_insert(index, insert, options);
4176 }
4177 break;
4178 case vbalanced_discard_code:
4179 {
4180 halfword index = tex_scan_box_register_number();
4181 halfword options = 0;
4182 while (1) {
4183 switch (tex_scan_character("drDR", 0, 1, 0)) {
4184 case 0:
4185 goto DISCARD;
4186 case 'd': case 'D':
4187 if (tex_scan_mandate_keyword("descend", 1)) {
4188 options |= balance_discard_descend;
4189 }
4190 break;
4191 case 'r': case 'R':
4192 if (tex_scan_mandate_keyword("remove", 1)) {
4193 options |= balance_discard_remove;
4194 }
4195 break;
4196 default:
4197 tex_aux_show_keyword_error("remove");
4198 goto DISCARD;
4199 }
4200 }
4201 DISCARD:
4202 tex_vbalanced_discard(index, options);
4203 }
4204 break;
4205 case vbalanced_deinsert_code:
4206 {
4207 halfword index = tex_scan_box_register_number();
4208 halfword options = 0;
4209 while (1) {
4210 switch (tex_scan_character("dfDF", 0, 1, 0)) {
4211 case 0:
4212 goto DEINSERT;
4213 case 'd': case 'D':
4214 if (tex_scan_mandate_keyword("descend", 1)) {
4215 options |= balance_deinsert_descend;
4216 }
4217 break;
4218 case 'f': case 'F':
4219 if (tex_scan_mandate_keyword("force", 1)) {
4220 switch (tex_scan_character("dhDH", 0, 1, 0)) {
4221 case 'd': case 'D':
4222 if (tex_scan_mandate_keyword("forcedepth", 6)) {
4223 options |= balance_deinsert_linedepth;
4224 }
4225 break;
4226 case 'h': case 'H':
4227 if (tex_scan_mandate_keyword("forceheight", 6)) {
4228 options |= balance_deinsert_lineheight;
4229 }
4230 break;
4231 default:
4232 tex_aux_show_keyword_error("forcedepth|forceheight");
4233 goto DEINSERT;
4234 }
4235 }
4236 break;
4237 default:
4238 tex_aux_show_keyword_error("forcedepth|forceheight");
4239 goto DEINSERT;
4240 }
4241 }
4242 DEINSERT:
4243 tex_vbalanced_deinsert(index, options);
4244 }
4245 break;
4246 case vbalanced_reinsert_code:
4247 {
4248 halfword index = tex_scan_box_register_number();
4249 halfword options = 0;
4250 while (1) {
4251 switch (tex_scan_character("dD", 0, 1, 0)) {
4252 case 0:
4253 goto REINSERT;
4254 case 'd': case 'D':
4255 if (tex_scan_mandate_keyword("descend", 1)) {
4256 options |= balance_reinsert_descend;
4257 }
4258 break;
4259 default:
4260 tex_aux_show_keyword_error("descend");
4261 goto REINSERT;
4262 }
4263 }
4264 REINSERT:
4265 tex_vbalanced_reinsert(index, options);
4266 }
4267 break;
4268 case flush_mvl_box_code:
4269 {
4270
4271 halfword index = tex_scan_integer(0, NULL, NULL);
4272 boxnode = tex_flush_mvl(index);
4273 }
4274 break;
4275 case insert_box_code:
4276 case insert_copy_code:
4277 {
4278 halfword index = tex_scan_integer(0, NULL, NULL);
4279 if (tex_valid_insert_id(index)) {
4280 boxnode = tex_get_insert_content(index);
4281 if (boxnode) {
4282 if (node_type(boxnode) == vlist_node) {
4283 if (code == insert_copy_code) {
4284 boxnode = tex_copy_node(boxnode);
4285 } else {
4286 tex_set_insert_content(index, null);
4287 }
4288 } else {
4289 tex_set_insert_content(index, null);
4290
4291 }
4292 }
4293 }
4294 break;
4295 }
4296 case local_left_box_box_code:
4297 {
4298 boxnode = tex_get_local_boxes(local_left_box_code);
4299 break;
4300 }
4301 case local_right_box_box_code:
4302 {
4303 boxnode = tex_get_local_boxes(local_right_box_code);
4304 break;
4305 }
4306 case local_middle_box_box_code:
4307 {
4308 boxnode = tex_get_local_boxes(local_middle_box_code);
4309 break;
4310 }
4311
4318 default:
4319 {
4320 quarterword direction;
4321 int justpack = 0;
4322 quarterword group = vbox_group;
4323 int mode = vmode;
4324 int adjusted = 0;
4325 switch (cur_list.mode) {
4326 case vmode:
4327 case internal_vmode:
4328 direction = dir_lefttoright;
4329 if (boxcontext == direct_box_flag) {
4330 adjusted = 1;
4331 }
4332 break;
4333 case hmode:
4334 case restricted_hmode:
4335 direction = (singleword) text_direction_par;
4336 break;
4337 case mmode:
4338 case inline_mmode:
4339 direction = (singleword) math_direction_par;
4340 break;
4341 default:
4342 direction = direction_unknown;
4343 break;
4344 }
4345 switch (code) {
4346 case tpack_code:
4347
4348 justpack = 1;
4349 group = vtop_group;
4350 break;
4351 case vpack_code:
4352
4353 justpack = 1;
4354
4355 break;
4356 case hpack_code:
4357 mode = hmode;
4358 justpack = 1;
4359 group = adjusted ? adjusted_hbox_group : hbox_group;
4360 break;
4361 case dpack_code:
4362
4363 justpack = 1;
4364 group = dbox_group;
4365 break;
4366 case vtop_code:
4367
4368
4369 group = vtop_group;
4370 break;
4371 case vbox_code:
4372
4373
4374
4375 break;
4376 case hbox_code:
4377 mode = hmode;
4378
4379 group = adjusted ? adjusted_hbox_group : hbox_group;
4380 break;
4381 case dbox_code:
4382
4383
4384 group = dbox_group;
4385 break;
4386 }
4387 tex_aux_scan_full_spec(boxcontext, group, direction, justpack, shift, slot, callback, leaders);
4388 tex_normal_paragraph(vmode_par_context);
4389 tex_push_nest();
4390 update_tex_internal_dir_state(0);
4391 cur_list.mode = - mode;
4392 if (mode == vmode) {
4393 cur_list.prev_depth = ignore_depth_criterion_par;
4394 if (every_vbox_par) {
4395 tex_begin_token_list(every_vbox_par, every_vbox_text);
4396 }
4397 } else {
4398 cur_list.space_factor = default_space_factor;
4399 if (every_hbox_par) {
4400 tex_begin_token_list(every_hbox_par, every_hbox_text);
4401 }
4402 }
4403 return;
4404 }
4405 }
4406
4407 tex_box_end(boxcontext, boxnode, shift, unset_noad_class, slot, callback, leaders);
4408}
4409
4410
4417
4418int tex_is_effectively_empty(halfword n, halfword options)
4419{
4420 while (n) {
4421 switch (node_type(n)) {
4422 case par_node:
4423 if (options & effective_empty_option_par) {
4424 switch (node_subtype(n)) {
4425 case vmode_par_par_subtype:
4426
4427 case hmode_par_par_subtype:
4428 case parameter_par_subtype:
4429
4430
4431 break;
4432 default:
4433 return 0;
4434 }
4435 break;
4436 } else {
4437 return 0;
4438 }
4439 case dir_node:
4440 if (options & effective_empty_option_dir) {
4441 break;
4442 } else {
4443 return 0;
4444 }
4445 case glue_node:
4446 if (options & effective_empty_option_indent_glue) {
4447 switch (node_subtype(n)) {
4448 case indent_skip_glue:
4449 case par_init_left_skip_glue:
4450 case par_init_right_skip_glue:
4451 break;
4452 default:
4453 return 0;
4454 }
4455 break;
4456 } else {
4457 return 0;
4458 }
4459 case hlist_node:
4460 if (options & effective_empty_option_indent_list) {
4461 switch (node_subtype(n)) {
4462 case indent_list:
4463 break;
4464 default:
4465 return 0;
4466 }
4467 break;
4468 } else {
4469 return 0;
4470 }
4471
4472
4473
4474 default:
4475 return 0;
4476 }
4477 n = node_next(n);
4478 }
4479 return 1;
4480} |